


// qmd.en.default.js

var locale='EN';
var domain='QMD';
var language='EN';
QSTR = {
	accountNotValidated:	'Your account is not yet validated',
	addAllToContacts:	'add all to contacts',
	addAnAnswerOption:	'Add an answer option',
	addEmail:	'Add email: ',
	addressBookSelectAll:	'\u002B\u0026nbsp;Select all',
	addressBookUnselectAll:	'\u002B\u0026nbsp;Unselect all',
	addToContacts:	'add to contacts',
	addUrl:	'Add URL',
	addUrlInvalid:	'The URL "%1$s" you submitted is invalid.  Please try again.',
	allFeaturedTitle:	'All Featured',
	answerTheNextQuestion:	'Answer the next question',
	askQuestionAndEarnPoints:	'Earn %d Q-Points if your question is one of the first 10 answered by the presenter.',
	askQuestionAndEarnPointsSingular:	'Earn %d Q-Point if your question is one of the first 10 answered by the presenter.',
	attachAFile:	'Attach a file',
	attachmentFile:	'File:',
	attachmentUrl:	'URL:',
	authorCommunities:	'Find me at these communities:',
	authorCommunity:	'Find me at this community:',
	authorRepliesPlural:	'%d Author Replies',
	authorRepliesSingular:	'%d Author Reply',
	authorsCommunities:	'Find us at these communities:',
	authorsCommunity:	'Find us at this community:',
	badChars:	'Invalid',
	baseHostAddress:	'my.quantiamd.com',
	beta:	'<div class\u003D"beta">beta</div>',
	cancel:	'Cancel',
	cancelButtonLabel:	'Cancel',
	CancelLiveAudioLabel:	'Cancel',
	cannotSendToEmailPlural:	'Univadis cannot send to the following email addresses:',
	cannotSendToEmailSingular:	'Univadis cannot send to the following email address:',
	cannotViewAttachment:	'Cannot view this attachment',
	castYourVoteBelow:	'Cast your vote below',
	changesSaved:	'Your changes have been saved',
	chatWithModerator:	'Chat with Moderator',
	clickHere:	'Click here',
	clickHereToResetPassword:	'<a onclick\u003D\'openForgotPassword(); return false;\' href\u003D\'#\'>Create new password</a>',
	clickOnAir:	'Click \'Turn On Air\' to start',
	clickToAddCommentLabel:	'Add your own comment',
	close:	'Close',
	closes:	'Closes',
	cme2HistoryEmailRequestSuccess:	'Your email request has been received',
	cme2HistoryValidDateRange:	'Please provide a valid date range in order to request your report.',
	cmeAvailable:	'awarded upon completion',
	cmeHasAwarded:	'<div>Awarded on %1$s</div><div><a href\u003D\'/home/cme\' ondblclick\u003D\'return false\'>View CME History</a></div>',
	commaSeparator:	', ',
	comment:	'Comment',
	commentAudioSubmitted:	'Thank you.  Your comment will be transcribed and online within 2 business days.',
	commentDayAgo:	'day ago',
	commentDaysAgo:	'days ago',
	commentEnterComment:	'Enter comment:',
	commentEnterReply:	'Enter reply:',
	commentFollowNeedToBeConfirmed:	'Only confirmed clinicians may follow discussions.  Please confirm now.',
	commentFormatPlural:	'%1$d comments in this discussion',
	commentFormatSingular:	'%1$d comment in this discussion',
	commentHoursAgo:	'hr ago',
	commentIsEmpty:	'The comment field is empty.  Please add a comment to submit',
	commentLast:	'last',
	commentLowerInitial:	'comment',
	commentMessageNeedToBeConfirmed:	'Only confirmed clinicians may participate in the full discussion.  Please confirm now.',
	commentMinutesAgo:	'min ago',
	commentMomentsAgo:	'moments ago',
	commentQPointLimitationText:	'(Limit of %d Q-Points per member per presentation.)',
	commentQPointLimitationTextSingular:	'(Limit of %d Q-Point per member per presentation.)',
	commentsAll:	'More Comments (%1$d)',
	commentsBeFirstToComment:	'Be the first to comment',
	commentSecondsAgo:	'sec ago',
	commentsFeatured:	'Featured Comments (%1$d)',
	commentsIncluding:	'%1$s Comments',
	commentsInDiscussionIncluding:	'%1$d comments in this discussion including:',
	commentsLowerInitial:	'comments',
	commentsRange:	'%1$d to %2$d',
	commentsSortedByFeatured:	'Featured',
	commentsSortedByReplies:	'Replies',
	commentsSortedByTime:	'Date',
	commentsSortedByVote:	'Likes',
	commentsViewAll:	'View all %1$d comments',
	commentUploadsPending:	'You have file uploads pending.  Please submit your comment after all pending file uploads have completed.',
	compose:	'Compose',
	composedFrom:	'composed from',
	composeMessage:	'Compose Message',
	confirmation:	'Confirmation',
	confirmDisconnect:	'Are you sure you want to disconnect from this representative?',
	confirmedResendPhone:	'Invitation email sent.',
	confirmedResendSingular:	'Invitation sent.',
	confirmedUpdate:	'Information updated.',
	confrimedResendPlural:	'Invitations sent.',
	contentDefaultDislaimer:	'\u00A92017 Univadis International, Inc. All rights reserved.',
	contentFormats:	'Content formats',
	continueButton:	'Continue',
	correctForQuiz:	'Correct!',
	correctRequiredInformation:	'Please correct the required information:',
	couldNotSendMessage:	'Could not send your message',
	countryOfPracticeRequired:	'Select your country of practice',
	createdLabel:	'Created: %s',
	createNewPwdPrompt:	'Please enter a password for this Univadis account.',
	dateAndTime:	'Date and Time',
	dateHeading:	'Date',
	dayAgo:	'1 day ago',
	daysAgo:	'%d days ago',
	defaultAddressText:	'Enter email addresses, separated by commas',
	defaultEmailBody:	'I recommend the following on Univadis:',
	defaultHomeReferral:	'I am a member of Univadis, a free clinician community, and would like to introduce you to the site.',
	disconnected:	'You have been disconnected from this representative',
	discussions:	'Discussions',
	discussionsIFollowTitle:	'Discussions I\'m Following',
	discussionTopics:	'Topics',
	duplicateEmail:	'This email address is in use',
	edit:	'Edit',
	editInvite:	'edit',
	editPictureBrowseButton:	'Browse',
	editPictureCanceled:	'Canceled',
	editPictureGetBackToYou:	'Our member services team will review this request within 24 hours.',
	editPictureRemovePhotoPrompt:	'Would you like to remove your picture?',
	editPictureSizeLimitError:	'The selected file exceeds the 5 MB size limit.',
	editPictureStopped:	'Stopped',
	editPictureSubmitPhotoPrompt:	'Would you like to submit your picture?',
	editPictureUploadComplete:	'Upload complete',
	editPictureUploading:	'Uploading...',
	editPictureURLLengthError:	'Please enter a valid URL or website name.',
	editPictureURLReceived:	'The following URL has been received:',
	emailAddressShortLabel:	'Email address:',
	emailConfirmDialogSentTo:	'We sent confirmation email to:',
	emailNotValidForDomain:	'This email address is not valid for this service.',
	emailPreferencesFailed:	'There was an error saving your email preferences.  Please contact Univadis Support.',
	emailPreferencesSaved:	'Thank you for updating your email preferences.  Your changes have been saved.',
	emailRequired:	'Please enter your email address',
	emailSentStatus:	'Email sent.',
	enrollPreviewTitle:	'Invitation Preview',
	enter3digitareacode:	'Please enter a valid 3 digit area code',
	enterGraduateUniversity:	'',
	enterLicensureYear:	'',
	enterMessage:	'Enter your message here',
	enterNamesOrEmails:	'Enter email address(es)',
	enterRating:	'Enter rating:',
	enterReplyComment:	'Enter your comment here',
	enterValidEmail:	'Please enter a valid email',
	enterValidEmailAddress:	'Please enter a valid email address',
	enterValidEmailOrPhone:	'Please enter valid email or cell phone number to send to',
	enterValidPhone:	'Please enter a valid phone number',
	enterValidZip:	'Please enter a valid ZIP',
	errorCheckingTextOnLabel:	'HasEnteredText doesn\'t make any sense for an answer label',
	errorCouldNotPreview:	'Could not preview your dataform.  There was no dataform id specified.',
	errorCreatingAccount:	'An error occurred creating this account',
	errorGeneric:	'Univadis encountered an error: %1$s',
	errorHideWhenComplete:	'You are trying to view content that you have already seen.  Unfortunately, this content can only be viewed by you once.',
	errorLoading:	'Unable to load content',
	errorLoadingComments:	'Unable to load comments',
	errorLoadingSubmission:	'Unable to load submission: %1$s',
	errorLoginConnectionFailed:	'Please retry login',
	errorNoPermission:	'There was a problem loading this content.  This may be because you do not have permission to view it.',
	errorParsing:	'Error loading: %1$s',
	errorQsclError:	'QSCL Error: %1$s',
	errorRemovingAttachment:	'There was an error removing the attachment: %1$s',
	errorSavingProfile:	'There was an error saving your profile',
	errorSettingTextOnLabel:	'Cannot set the text of an answer label',
	errorSubmitting:	'Error Submitting: %1$s',
	errorSubmittingSurvey:	'There was a problem submitting your survey results.  Please try again.',
	errorUnavailable:	'This content is currently unavailable.',
	ErrorWithLiveAudio:	'Error Streaming Audio ',
	event:	'Event',
	everythingIDontFollow:	'Everything I\'m Not Following',
	everythingIDontFollowTitle:	'Everything I\'m Not Following',
	everythingIFollow:	'Everything I\'m Following',
	eveythingIFollow:	'Everything I\'m Following',
	fileLabel:	'File:',
	finalAnswer:	'Submit',
	followButtonLabel:	'Follow',
	followButtonLabelFollowing:	'Following',
	followedDiscussions:	'Discussions you follow are listed below.',
	forgotPasswordButton:	'Create new password',
	forgotPasswordDupAccount:	'There is a problem with your account.<br/>Please <a href\u003D\'#\' onclick\u003D\'goToSupport();return false;\'> contact member support.</a>',
	forgotPasswordHeader:	'Create new password?',
	forgotPasswordSuccess:	'<div style\u003D"margin-bottom: 12px;">\u000D\u000A<b>If the provided email address is for a valid account,</b> a reset password message will be sent to: %1$s\u000D\u000A</div>\u000D\u000A<div>\u000D\u000AFor additional assistance please contact Univadis Member Services at (888) 729-4546 (Mon-Fri, 8-7ET).\u000D\u000A</div>',
	go:	'Go',
	groupCheckedMessage:	'Added to my resources',
	groupUncheckedMessage:	'Add to my resources',
	headerSearchBox:	'Search',
	hereIsHowYourColleaguesHaveAnswered:	'Here\'s how your colleagues have answered:',
	hideAll:	'(Hide all)',
	hourAgo:	'1 hour ago',
	hoursAgo:	'%d hours ago',
	hoursPlayerIndicatorTime:	'%1$d:%2$02d:%3$02d | %4$d:%5$02d:%6$02d',
	hoursPlayerindicatorTime2014:	'%1$d:%2$02d:%3$02d',
	imageContestPointLimitationText:	'100 winners will be randomly selected to receive<strong><br>%d Q-Points</strong> for answering all the questions in this contest correctly.',
	imageContestPointLimitationTextSingular:	'100 winners will be randomly selected to receive<strong><br>%d Q-Point</strong> for answering all the questions in this contest correctly.',
	imageContestPointText:	'Give the correct answers and be<br>entered to win <strong><span style\u003D"color:#009ac8">%d Q-Points</span></strong>',
	imageContestPointTextSingular:	'Give the correct answers and be<br>entered to win <strong><span style\u003D"color:#009ac8">%d Q-Point</span></strong>',
	inboxempty:	'My Messages',
	inboxWithNewCount:	'My Messages (%1$d new)',
	inContacts:	'in contacts',
	incorrectForQuiz:	'Incorrect!',
	infoPanelQpCMEAwardedOn:	'Awarded on',
	invalidCommentCharacter:	'Your comment text includes some invalid characters. Please do not include symbols or "emojis".',
	invalidCredentials:	'Invalid characters in credentials',
	invalidCredentialsEntered:	'Invalid characters for credential',
	invalidEmailAddress:	'Invalid email address',
	invalidInvitation:	'Invalid invitation',
	invalidLicensureYear:	'',
	invalidName:	'Invalid characters in name',
	invalidZip:	'Invalid characters in zip code',
	invitationsSent:	'Invitations Sent',
	invited:	'Invited',
	inviteNewPhysician:	'Invite a New Physician',
	iPodTouchCantCall:	'iPod touch cannot place phone calls',
	joined:	'Joined',
	joining:	'Joining...',
	joinNow:	'Join\u0026nbsp;Now',
	joinQuantiaMD:	'Join Univadis',
	joinTheDiscussion:	'Join the discussion',
	joinTheDiscussionCantComment:	'Discussion',
	keywordCategoryNarrowResults:	'Narrow results:',
	keywordCategoryResults:	'%d results',
	lastActivityLabel:	'Last activity: %s',
	lastComment:	'%1$d Comment',
	lastCommentDayAgo:	'%1$d Comment, last 1 day ago',
	lastCommentDaysAgo:	'%1$d Comment, last %2$d days ago',
	lastCommentHourAgo:	'%1$d Comment, last 1 hour ago',
	lastCommentHoursAgo:	'%1$d Comment, last %2$d hours ago',
	lastCommentMinuteAgo:	'%1$d Comment, last 1 minute ago',
	lastCommentMinutesAgo:	'%1$d Comment, last %2$d minutes ago',
	lastCommentMomentsAgo:	'%1$d Comment, last moments ago',
	lastComments:	'%1$d Comments',
	lastCommentsDayAgo:	'%1$d Comments, last 1 day ago',
	lastCommentsDaysAgo:	'%1$d Comments, last %2$d days ago',
	lastCommentSecondAgo:	'%1$d Comment, last 1 second ago',
	lastCommentSecondsAgo:	'%1$d Comment, last %2$d seconds ago',
	lastCommentsHourAgo:	'%1$d Comments, last 1 hour ago',
	lastCommentsHoursAgo:	'%1$d Comments, last %2$d hours ago',
	lastCommentsMinuteAgo:	'%1$d Comments, last 1 minute ago',
	lastCommentsMinutesAgo:	'%1$d Comments, last %2$d minutes ago',
	lastCommentsMomentsAgo:	'%1$d Comments, last moments ago',
	lastCommentsSecondAgo:	'%1$d Comments, last 1 second ago',
	lastCommentsSecondsAgo:	'%1$d Comments, last %2$d seconds ago',
	lastX:	'last %1$s',
	leaving:	'Leaving...',
	less:	'Less',
	LiveEvent:	'Live Event',
	LiveEventActiveChats:	'Active Chats',
	LiveEventAlertNoModerAvailable:	'No presenter or moderator is available to forward this message to. ',
	LiveEventAlertSelectRcpt:	'Please select a recipient',
	LiveEventAudioAlert:	'Please check the audio server. May be hangup the phone and reestablish the conference call.',
	LiveEventCancelRefer:	'Cancel',
	LiveEventChatAvailable:	'Available',
	LiveEventChatHelpMsg:	'Type your message here...',
	LiveEventChatModeratorOfflineBtnText:	'Moderator is off-line',
	LiveEventChatModeratorOnlineBtnText:	'Moderator is available',
	LiveEventChatOffline:	'Off-Line',
	LiveEventChatStatus:	'Status:',
	LiveEventChatWithModerator:	'Chat with moderator',
	LiveEventComingSoon:	'Coming soon',
	LiveEventConfirmGoOffAir:	'Are you sure you want to put the conference off-air? Once a conference has been placed off-air it can not be resumed.',
	LiveEventConfirmGoOnAir:	'Are you sure you want to put the conference on-air?',
	LiveEventForwardChat:	'Forward',
	LiveEventForwardMsg:	'Forward this message',
	LiveEventGoNow:	'Go Now',
	LiveEventInfoPanelLabel:	'Conference Info',
	LiveEventLoggedOutHeading:	'Join This Event',
	LiveEventLoggedOutMsg:	'Please sign-in to your Univadis account or create an account for free.',
	LiveEventModerator:	'Moderator',
	LiveEventMsgPanelLabel:	'Message',
	LiveEventNoneScheduled:	'No Events Scheduled',
	LiveEventOffline:	'offline',
	LiveEventOnAir:	'On Air',
	LiveEventOver:	'The event is over.',
	LiveEventParticipants:	'Participants',
	LiveEventPleaseJoinAlertMsg:	'Please Join Event',
	LiveEventPresenter:	'Presenter',
	LiveEventPrevSlides:	'Previous Slides',
	LiveEventRemoveUser:	'[remove]',
	LiveEventSaveSeat:	'Save a Seat',
	LiveEventSchedule:	'Event Schedule',
	LiveEventSchedulePanel:	'Schedule',
	LiveEventSchedulerNotLoggedInMsg:	'To view event information, please sign-in to your Univadis account or create an account for free.',
	LiveEventSeatReserved:	'Seat Reserved',
	LiveEventSendChat:	'Send',
	LiveEventSlides:	'Slides',
	LiveEventsMeetingAnnouncements:	'Meeting Announcements',
	LiveEventStartsIn:	'Starts in ',
	LiveEventTurnOnAir:	'Turn On Air',
	loadingComments:	'Loading comments...',
	lockedMessage:	'Locked Message',
	lockMessage:	'Lock message',
	loggedIntoConferenceTwice:	'Another instance of the conference is open with your user id.  That instance will be closed.',
	loggedIntoConferenceTwiceWarn:	'Another instance of the conference has logged in with your user id. This instance will be closed.',
	loginFailed:	'Your email or password is incorrect.',
	loginInvalidEmail:	'This email address is not valid for login for Univadis.',
	loginInvalidPassword:	'Password incorrect.<br><a onclick\u003D\'openForgotPassword(); return false;\' href\u003D\'#\'>Click here</a> to have your password emailed to you.',
	loginPasswordIncorrectText:	'Password incorrect.',
	loginPasswordSentTo:	'Email has been sent to:<br />%1$s<br /><br />Please go to your email account to find Create New Password messsage.<br/><br/>',
	loginSubmit:	'Submit',
	loginSubmitting:	'Sending...',
	manageContacts:	'You can manage your contacts from your own inbox',
	meetingDuration:	'Meeting Duration:',
	meetingInProgress:	'Meeting in Progress',
	menuInbox:	'My Inbox',
	menuMyQuantiaMD:	'Univadis',
	messageConfirmation:	'Message confirmation',
	messageLabel:	'Message',
	messageLockedInfo:	'Please enter your Univadis password to continue',
	messageNotSent:	'Unable to send the message.',
	messageNotSentCheckAddresses:	'We were unable to send your message. Please check the email addresses and try again.',
	messages:	'Messages',
	messageSent:	'Message Sent',
	minuteAgo:	'1 minute ago',
	minutesAgo:	'%d minutes ago',
	mismatch:	'Mismatch - please try again',
	missing_id:	'No reward of this type is available',
	mobileComments:	'Discussion',
	mobileConferenceAccessDenied:	'You may not have permission to view this conference.',
	mobileConferenceExpired:	'This conference has expired.',
	mobileEmailRequired:	'',
	mobileInfo:	'Info',
	mobileISI:	'Important Safety Information',
	mobileOutline:	'Outline',
	mobilePlayer:	'Player',
	mobileProblemLoading:	'You may not have permission to view this content',
	mobileTopic:	'Topic',
	moderatorOffline:	'Moderator is Offline',
	momentsAgo:	'Moments ago',
	monitorOptInNotChecked:	'\u0026nbsp;',
	more:	'More',
	msgSent:	'Your message was sent to',
	msgSentConfirmation:	'Your message was sent.',
	mustEnterANumberValue:	'You must enter a number value in this field',
	mustEnterAValue:	'You must enter a value in this field',
	mustIncludeReferralLink:	'Your email must include a link to this content.  Would you like to revert to the original email?',
	myInterestsLimit:	'You may select up to 20 interests.',
	myPublicDiscussionsTitle:	'Discussions I\'m Following',
	myRepLabel:	'My Rep',
	name:	'Name',
	nameEmailColumnTitle:	'Name/Email',
	needReview:	'Need Review',
	newComments:	'%d new',
	newDiscussionEnterASubject:	'Enter a subject',
	newsCuratorLabel:	'Curated by: ',
	newsReferencesLabel:	'References: ',
	newsSourceLabel:	'Source: ',
	nextOnPiNext:	'Taking you to addtional programs and resources...',
	nextOnPiPlayer:	'Thanks for participating.',
	nextOnQuantiaMD:	'Next on Univadis:',
	ninetySeconds:	'90 seconds',
	noComments:	'No Comments in this discussion',
	noCommentsStart:	'Start the discussion by adding a comment',
	noEmailAddressesSaved:	'No email addresses have been saved',
	noRepliesAddYours:	'No replies.  Add yours below.',
	notYou:	'Not %s?\u0026nbsp;\u0026nbsp;',
	NowPlayingLiveEvent:	'Now Playing',
	numComments:	'%1$d Comments',
	officeZip:	'Office ZIP',
	ok:	'OK',
	oneResult:	'1 Result',
	oneSecond:	'\u0026nbsp;in\u0026nbsp;%1$d second\u0026nbsp;\u0026nbsp;',
	optInLabel:	'Opt In',
	optOutLabel:	'Opt Out',
	other:	'Other',
	participants:	'Participants',
	passwordChanged:	'Your password has been changed.',
	passwordLabel:	'Password:',
	passwordMismatch:	'Password and Confirm Password do not match',
	passwordNotChanged:	'Your password cannot be reset by this link.',
	peerMessageArchived:	'Archived',
	peerMessageDeleted:	'Deleted',
	peerMessageInvalidRecipient:	'Invalid recipient. Please correct or delete to continue.',
	phoneLabel:	'Phone:',
	pinLabel:	'PIN:',
	playerAlertDialogTitle:	'',
	playerBuffering:	'Buffering',
	playerDone:	'Done',
	playerIndicatorTime:	'%1$d:%2$02d | %3$d:%4$02d',
	playerindicatorTime2014:	'%1$d:%2$02d',
	playerLastViewed:	'You last viewed this on %1$s',
	playerOrText:	'or',
	playerPaused:	'Paused',
	playerPlaying:	'Playing',
	pluralSeconds:	'\u0026nbsp;in\u0026nbsp;%1$d seconds\u0026nbsp;\u0026nbsp;',
	postQuestionAddAttachment:	'Add Attachment',
	postQuestionAttachmentStillUploading:	'It appears that you are still uploading one or more attachments.  Please wait until all of the attachments have finished sending before previewing.',
	postQuestionDefaultTitle:	'--untitled--',
	postQuestionDeleteQuestion:	'Delete question',
	postQuestionDeleteQuestionConfirmation:	'Are you sure you want to delete this question?',
	postQuestionMobileDefaultTitle:	'Enter a title for your question',
	postQuestionMoreAnswers:	'Please provide at least two answer options in order to include your question.\u000D\u000A',
	postQuestionNoMembers:	'Please invite at least one participant',
	postQuestionNoText:	'Please provide a message in order to start your discussion.\u000D\u000A',
	postQuestionNoTitle:	'Please provide a subject in order to start your discussion.\u000D\u000A',
	postQuestionNoTopics:	'Please add at least one topic in order to start your discussion',
	postQuestionSurveyAnswer:	'Answer Option %1$d',
	postQuestionSurveyQuestion:	'Question %1$d',
	postQuestionTooLong:	'The text to be published that you entered is %1$s characters long.  The maximum limit is 64000 characters.  \n\nExtra characters may be added when pasting from Microsoft Word.  If this is the case, try attaching the word document instead. \n\nPlease shorten your text and try again.',
	profileInformation:	'Profile Information',
	profileNewPasswordsDontMatch:	'The new passwords you entered do not match',
	profileReverify:	'To change your name, title or institution, you will need to <a href\u003D\'#\' class\u003D\'reverifyLink\' onclick\u003D\'reverify(); return false\'>verify your identity again</a>',
	publishedLabel:	'Published:',
	pwdResetInstructionsSent:	'Instructions on creating a new password have been sent to<br/>\u0026lt;%1$s\u0026gt;.<br/>',
	qpDonationError:	'Donation cannot exceed Q-Point balance.',
	qpDonationProcessed:	'Thank you! <br/><br/> Your donation of %d Q-Points has been processed.',
	qpDonationUserInputErr:	'Only positive whole numbers are valid.',
	qPointsHasAwarded:	'<div>Awarded on %1$s</div><div><a href\u003D\'/home/qpoints\' ondblclick\u003D\'return false\'>View Q-Point History</a></div>',
	qsclCantCompareFunctions:	'Cannot compare function primitives',
	qsclCantFindFunction:	'%1$s is not a known functions',
	qsclCantParseNumber:	'Could not parse number! Make sure you aren\'t using an identifier that starts with a number.',
	qsclCouldntFindAnswer:	'Could not find the answer specified',
	qsclCouldntFindQuestion:	'Could not find the question specified',
	qsclCouldntFindScreen:	'Could not find the screen specified',
	qsclIndexOutOfBounds:	'Index out of bounds: %1$d requested, but list is only %2$d long',
	qsclParametersNotBool:	'All parameters passed to the \'%1$s\' operator must be bools',
	qsclParametersNotNumber:	'All parameters passed to the \'%1$s\' operator must be numbers',
	qsclParametersNotString:	'All parameters passed to the \'%1$s\' operator must be strings',
	qsclRequires1or2Parameters:	'The \'%1$s\' operator requires one or two values',
	qsclRequires1Parameter:	'The \'%1$s\' operator requires exactly one value',
	qsclRequires2or3Parameters:	'The \'%1$s\' operator requires two or three values',
	qsclRequires2Parameters:	'The \'%1$s\' operator requires at least two values',
	qsclRequires3Parameters:	'The \'%1$s\' operator requires three values',
	qsclRequiresAtLeast1Parameter:	'The \'%1$s\' operator requires at least one value',
	qsclRequiresBetweenNumberOfParameters:	'The \'%1$s\' function requires between %2$d and %3$d parameter(s)',
	qsclRequiresFirstParameterBool:	'The first parameter of \'%1$s\' must be a boolean value',
	qsclRequiresFirstParameterIdentifier:	'The first parameter of \'%1$s\' must be an identifier',
	qsclRequiresFirstParameterList:	'The first parameter of \'%1$s\' must be a list value',
	qsclRequiresFirstParameterNumber:	'The first parameter of \'%1$s\' must be a number value',
	qsclRequiresListOfIdentifiers:	'The \'%1$s\' requires a list of identifiers',
	qsclRequiresNumberOfParameters:	'The \'%1$s\' function requires exactly %2$d parameter(s)',
	qsclRequiresSecondsParameterList:	'The second parameter of \'%1$s\' must be a list value',
	qsclRequiresSecondsParameterNumber:	'The second parameter of \'%1$s\' must be a number value',
	qsclTooManyAnswersSelected:	'There is more than one answer selected',
	qsclUnexpectedEndOfFile:	'Reached the end of the file, but expected \')\'',
	qsclUnexpectedParen:	'Reached an unexpected \')\'.  Please make sure your parenthesis match.',
	qspacePromptDelete:	'Are you sure you want to delete this Private Discussion?',
	qspacePromptEnd:	'Are you sure you want to end this Private Discussion?',
	qSpacesUploadCancel:	'Cancel',
	qSpacesUploadDelete:	'Delete',
	qSpacesUploadView:	'View',
	quantiaIsFree:	'Univadis is free',
	questionExpectingNumberField:	'Please enter a number into the \'%1$s\' field.',
	questionExpectingNumberFieldNoLabel:	'Please enter a number into this field.',
	questionFreeformAudioPromptTitle:	'Answer question:',
	questionOneRequiredField:	'You must check off \'%1$s\' before continuing. ',
	questionPleaseAnswerField:	'You must answer the \'%1$s\' field before continuing.',
	questionPleaseAnswerFieldNoLabel:	'You must answer this field before continuing.',
	questionResultsLoading:	'Loading',
	questionSelectAnAnswer:	'Please select an answer before continuing.',
	questionSelectAtLeastOne:	'You must select at least %1$s answer before continuing.',
	questionSelectedTooMany:	'You must select at most %1$d answers for the \'%2$s\' field before continuing.',
	questionSelectMoreThanOne:	'You must select at least %1$d answers for the \'%2$s\' field before continuing.',
	QuitLiveAudioLabel:	'Quit',
	quizAnswerExplanationLabel:	'Explanation:',
	quizIPQuestionBlockTitle:	'You may also be interested in',
	quizNextInvitationText:	'Are you up to date? Test your knowledge on the latest clinical evidence.',
	quizQuestionBlockTitle:	'Quiz question',
	quizQuestionIndicationText:	'Select the correct answer',
	ratingCountFormat:	'%1$d\u0026nbsp;ratings',
	ratingThankYou:	'Your rating has been submitted.',
	readString:	'Read',
	recipients:	'recipients',
	referBody:	'I just saw "%1$s" on Univadis, an online community for clinicians, and wanted to share it with you.\n\nClick on the link below or cut and paste it into your Web browser.\u000D\u000A\n%2$s\n\u000D\u000ARegistration is simple and the service is free.\n\n\n\nThanks,\n\n%3$s',
	referEatsmartSubject:	'EatSmart: "%1$s"',
	referInvalidEmail:	'\'%1$s\' isn\'t a valid Email address.  Please correct this and try again.',
	referralHeightLatin:	'460px',
	referralHeightNonLatin:	'460px',
	referSent:	'Email sent to %1$s',
	referSubject:	'I recommend the following ... "%1$s"',
	referThisPresentation:	'Refer colleagues via email',
	referWithoutEmail:	'Please enter an email address to continue.',
	refreshing:	'Refreshing...',
	reg_alreadyRegistered:	'is already registered on Univadis',
	reg_EmailError:	'An error occurred while sending an email to the following address:',
	reg_enterPassword:	'Is this you? Enter your password to continue.',
	reg_furtherAssistance:	'For further assistance, please <a href\u003D"/home/corporate_contact_us">Contact Member Support</a>',
	reg_incorrectPassword:	'The password you entered is incorrect.',
	reg_instructionsSent:	'Instructions to create a new password have been sent to the following email address:',
	reg_MemberSupport:	'Please contact Member Service at',
	reg_needHelp:	'Need more help?',
	reg_sendInstructions:	'<a onclick\u003D"registerDialog.forgotPasswordSubmit(); return false;">Click here</a> and instructions on creating a new password will be sent to the above email address.',
	reg_tryAgain:	'Please try again or choose a different option.',
	register:	'Register',
	registerAccountAlreadyExists:	'This email address is already registered to an existing Univadis account. <br/>Click below to create a new password or contact <a href\u003D"/home/corporate_contact_us" >member support</a>.',
	registerAccountAlreadyExistsPasswordIncorrect:	'This email address is registered to an existing Univadis account.',
	registerAccountAlreadyExistsPasswordIncorrectText:	'This email address is registered to an existing Univadis account.',
	registerAccountAlreadyExistsText:	'This email address is already registered to an existing Univadis account. <br/>Click below to create a new password or contact <a href\u003D"/home/corporate_contact_us" >member support</a>.',
	registerAccountEmailDomainReserved:	'This email domain is reserved.',
	registerAgreeToTerms:	'You must agree to our terms of use before continuing',
	registerCheckMonitorAgreeToTerms:	'To participate as a monitor, you must agree to the Monitor User Terms and Conditions',
	registerEmailRejected:	'Invalid email address',
	registerEmptyEmail:	'Please enter an email address',
	registerEnterBirthDay:	'Enter your day of birth',
	registerEnterBirthMonth:	'Enter your month of birth',
	registerEnterBirthYear:	'Enter your year of birth',
	registerEnterCity:	'Enter your city',
	registerEnterCredentials:	'Select your credential',
	registerEnterDigitsInFax:	'Enter digits only in the fax number',
	registerEnterFax:	'Enter a fax number',
	registerEnterFirstName:	'Enter your first name',
	registerEnterGender:	'Enter your gender',
	registerEnterInstitution:	'Enter your institution',
	registerEnterKatakanaFirstName:	'Enter katakana first name',
	registerEnterKatakanaFullWidthFirstName:	'Enter full width katakana characters in your first name',
	registerEnterKatakanaFullWidthLastName:	'Enter only full width katakana characters in last name',
	registerEnterKatakanaLastName:	'Enter katakana last name',
	registerEnterLastName:	'Enter your last name',
	registerEnterPhone:	'Enter your phone number',
	registerEnterSpecialty:	'Select a specialty',
	registerEnterState:	'Enter your state',
	registerEnterSubSpecialty:	'Select a subspecialty',
	registerEnterTitle:	'Enter your title',
	registerEnterValidBirthdayOld:	'Please confirm birthday',
	registerEnterValidBirthdayYoung:	'Please verify information qualified for a physician',
	registerEnterZIPorCountry:	'Enter ZIP or Postal Code',
	registeringLabel:	'Registering',
	registerInvalidCharactersInEmail:	'Please enter only letters, digits, and punctuation \'.\', \'_\', \'-\' or \'@\' in your email address',
	registerInvalidEmail:	'Invalid email address',
	registerInvalidTelephone:	'Enter 9-11 digits for telephone',
	registerInvalidZip:	'Enter a 7 digit zip code',
	registerPasswordLength:	'6',
	registerPasswordTooShort:	'Minimum 6 characters',
	registerPasswordTooShortFullMsg:	'Password minimum 6 characters',
	registerPleaseCorrect:	'Please correct the following:',
	registerPrimarySpecialtyHelpText:	'Select your primary specialty',
	registerRegIDFieldMissing:	'Fill out the \'%1$s\' field.',
	remind:	'Remind',
	reminded:	'Reminded',
	removeRep:	'Remove Rep',
	removeSavedButton:	'Remove',
	reply:	'\u002B reply',
	replyLabel:	'Reply',
	replyMobile:	'\u002B Reply',
	required:	'Required',
	requiredInfoMissingError:	'Required information missing',
	resend:	'Resend',
	resendColumnTitle:	'Re-Send',
	resendInvitePhone:	'Re-send invitation email to:',
	resendInvitePlural:	'Re-send %d invitations?',
	resendInviteSingular:	'Re-send invitation?',
	resetPassword:	'Create new password',
	responded:	'Responded',
	responseRating:	'Rating: %1$f (%2$d)',
	RetryLiveAudioLabel:	'Retry',
	revalidationRequired:	'Changing your NPI number will revalidate your account.  Are you sure you want to change your NPI number?',
	reward_missing_id:	'This award is not available',
	reward_not_enough_qpoints:	'You do not have enough QPoints for this award',
	reward_too_many_requests:	'You are not eligible to receive this many awards of this type',
	savedTooMany:	'You can save a maximum of 20 items.  Please delete some and try again.',
	search:	'Search',
	searchWithin:	'Search Within',
	searchWithinResults:	'Search within results',
	secondAgo:	'1 second ago',
	secondsAgo:	'%d seconds ago',
	securityAlert:	'While your message is secure, it should not include patient information.',
	seeMore:	'See More',
	selectAllWithParens:	'(select all)',
	selectAProduct:	'Select at least one product',
	selectAtLeastAnswer:	'You must select at least %1$d answer before continuing.',
	selectAtLeastAnswers:	'You must select at least %1$d answers before continuing.',
	selectAtMostAnswer:	'You must select at most %1$d answer before continuing.',
	selectAtMostAnswers:	'You must select at most %1$d answers before continuing.',
	selectTopicBeforeSubmitting:	'Please add a topic before submitting this page',
	sendButtonText:	'Send email',
	sendEmail:	'Send\u0026nbsp;email',
	senderLabel:	'From:',
	sendFailed:	'Send failed',
	sending:	'Sending...',
	sendInvitationTo:	'Invite colleagues to this discussion:',
	sendReminder:	'Send Reminder',
	sensei:	'Sensei',
	sent:	'Sent',
	serverError:	'Univadis encountered an error.  Please contact support.',
	serviceLink:	'My Reps',
	setDateAndTime:	'Set Date and Time',
	share:	'Share',
	shareFiveStarPointRatingWithQPoints:	'Share this 5-star presentation with a colleague and earn %d QPoints\u002A',
	showall:	'Show all',
	showAllSlideFromPicker:	'Show To All',
	showingNofM:	'%d of %d results',
	showMeSlideFromPicker:	'Show',
	signIn:	'Sign In',
	signUp:	'Sign up',
	signUpInvitation:	'Sign up for free',
	sortByComments:	'Sort by comments',
	sortByLastComment:	'Sort by last comment',
	sortByTitle:	'Sort by title',
	startADiscussion:	'Start a Discussion',
	status:	'Status',
	statusColumnTitle:	'Status',
	subjectLabel:	'Subject',
	subjectTooLong:	'Subject line too long',
	submit:	'Submit',
	submitCommentButtonText:	'Submit\u0026nbsp;Comment',
	submitCommentReplyText:	'Post A Reply',
	submitLabel:	'Submit',
	submittingComment:	'Submitting comment...',
	submittingLabel:	'Submitting',
	submittingWithElipsis:	'Submitting ...',
	surveyResultsDefaultTitle:	'Answer:',
	swfUploadTooBig:	'File is too big.',
	tabMenueEducationLabel:	'Education',
	tabMenueNewsLabel:	'News',
	tabTitle:	'%s (%d)',
	textBoxAudioPrompt:	'Enter text:',
	textBoxAudioWillBeTranscribed:	'... awaiting transcription ...',
	thankYouForPosting:	'Thank you. Your post has been submitted.',
	thankYouForReferring:	'Your referral message has been sent.',
	theAnswerIs:	'The answer is "%1$s".',
	too_many_requests:	'You have exceeded the number of awards of this type that you may receive',
	tooShort:	'At least 6',
	topicListFormatter:	'%1$s, ',
	topicsIFollowTitle:	'Topics I\'m Following',
	topicsLabel:	'Topics:',
	touchToEnterComments:	'Tap to comment',
	unknown:	'Unknown',
	unlockMessage:	'Unlock message',
	unread:	'Unread',
	unselectAllWithParens:	'(unselect all)',
	updatedOnLabel:	'Updated On:',
	uploadCancel:	'Cancel',
	uploadClear:	'Clear',
	uploadProcessing:	'Processing...',
	uploadRemove:	'Remove',
	upvoteCommentAndEarnPoints:	'Complete this presentation and \u201CLike\u201D at least one question and author reply for a chance at one of fifty %d Q-Point awards.',
	upvoteCommentAndEarnPointsSingular:	'Complete this presentation and \u201CLike\u201D at least one question and author reply for a chance at one of fifty %d Q-Point awards.',
	upvoteSlidePromoText:	'50 participants will be randomly selected and awarded %d Q-Points',
	upvoteSlideStep1:	'Complete this presentation',
	upvoteSlideStep2:	'Review the questions and author replies below',
	upvoteSlideStep3:	'"Like" at least one question and author reply',
	upvoteSlideTitle:	'Vote for Your Favorite Questions and Answers',
	upvoteSlideToParticipate:	'To Participate',
	urlLabel:	'Add URL:',
	validateToContact:	'Available only to confirmed clinicians',
	viewAll:	'(View all)',
	viewed:	'Viewed',
	viewInbox:	'View my inbox',
	viewMoreN:	'See next %d',
	viewNextN:	'View Next %1$d',
	voteCountFormat:	'%1$d\u0026nbsp;votes',
	voteCountSingularFormat:	'%1$d\u0026nbsp;vote',
	waitForModerator:	'Please wait for the moderator',
	watchDemo:	'Watch a Demo',
	welcomeUser:	'Welcome %s %s',
	youMayBeInterestedIn:	'You may also be interested in',
	yourRequestHasBeenSent:	'Your request has been sent',
nil:''};




// mootools.v1.3.2.js

/*
---
MooTools: the javascript framework

NOTE: Quantia 06/16/2013: have JSON.encode and JSON.decode invoke stringify and parse if available,
      and fall through to MooTools's implementations (which are slightly more forgiving of ' vs ")
      if native implementations throw
      
web build:
 - http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7

packager build:
 - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff

/*
---

name: Core

description: The heart of MooTools.

license: MIT-style license.

copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/).

authors: The MooTools production team (http://mootools.net/developers/)

inspiration:
  - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)
  - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)

provides: [Core, MooTools, Type, typeOf, instanceOf, Native]

...
*/


(function(){

this.MooTools = {
	version: '1.3.2',
	build: 'c9f1ff10e9e7facb65e9481049ed1b450959d587'
};


// typeOf, instanceOf

var typeOf = this.typeOf = function(item){
	if (item == null)
		return 'null';
	if (item.$family)
		return item.$family();

	if (item.nodeName) {
		if (item.nodeType == 1)
			return 'element';
		if (item.nodeType == 3)
			return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace';
	} else if (typeof item.length == 'number') {
		if (item.callee)
			return 'arguments';
		if ('item' in item)
			return 'collection';
	}

	return typeof item;
};

var instanceOf = this.instanceOf = function(item, object){
	if (item == null) return false;
	var constructor = item.$constructor || item.constructor;
	while (constructor){
		if (constructor === object) return true;
		constructor = constructor.parent;
	}
	return item instanceof object;
};

// Function overloading

var Function = this.Function;

var enumerables = true;
for (var i in {toString: 1}) enumerables = null;
if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];

Function.prototype.overloadSetter = function(usePlural){
	var self = this;
	return function(a, b){
		if (a == null) return this;
		if (usePlural || typeof a != 'string'){
			for (var k in a) self.call(this, k, a[k]);
			if (enumerables) for (var i = enumerables.length; i--;){
				k = enumerables[i];
				if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
			}
		} else {
			self.call(this, a, b);
		}
		return this;
	};
};

Function.prototype.overloadGetter = function(usePlural){
	var self = this;
	return function(a){
		var args, result;
		if (usePlural || typeof a != 'string') args = a;
		else if (arguments.length > 1) args = arguments;
		if (args){
			result = {};
			for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
		} else {
			result = self.call(this, a);
		}
		return result;
	};
};

Function.prototype.extend = function(key, value){
	this[key] = value;
}.overloadSetter();

Function.prototype.implement = function(key, value){
	this.prototype[key] = value;
}.overloadSetter();

// From

var slice = Array.prototype.slice;

Function.from = function(item){
	return (typeOf(item) == 'function') ? item : function(){
		return item;
	};
};

Array.from = function(item){
	if (item == null) return [];
	return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
};

Number.from = function(item){
	var number = parseFloat(item);
	return isFinite(number) ? number : null;
};

String.from = function(item){
	return item + '';
};

// hide, protect

Function.implement({

	hide: function(){
		this.$hidden = true;
		return this;
	},

	protect: function(){
		this.$protected = true;
		return this;
	}

});

// Type

var Type = this.Type = function(name, object){
	if (name){
		var lower = name.toLowerCase();
		var typeCheck = function(item){
			return (typeOf(item) == lower);
		};

		Type['is' + name] = typeCheck;
		if (object != null){
			object.prototype.$family = (function(){
				return lower;
			}).hide();
			//<1.2compat>
			object.type = typeCheck;
			//</1.2compat>
		}
	}

	if (object == null) return null;

	object.extend(this);
	object.$constructor = Type;
	object.prototype.$constructor = object;

	return object;
};

var toString = Object.prototype.toString;

Type.isEnumerable = function(item){
	return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' );
};

var hooks = {};

var hooksOf = function(object){
	var type = typeOf(object.prototype);
	return hooks[type] || (hooks[type] = []);
};

var implement = function(name, method){
	if (method && method.$hidden) return;

	var hooks = hooksOf(this);

	for (var i = 0; i < hooks.length; i++){
		var hook = hooks[i];
		if (typeOf(hook) == 'type') implement.call(hook, name, method);
		else hook.call(this, name, method);
	}
	
	var previous = this.prototype[name];
	if (previous == null || !previous.$protected) this.prototype[name] = method;

	if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){
		return method.apply(item, slice.call(arguments, 1));
	});
};

var extend = function(name, method){
	if (method && method.$hidden) return;
	var previous = this[name];
	if (previous == null || !previous.$protected) this[name] = method;
};

Type.implement({

	implement: implement.overloadSetter(),

	extend: extend.overloadSetter(),

	alias: function(name, existing){
		implement.call(this, name, this.prototype[existing]);
	}.overloadSetter(),

	mirror: function(hook){
		hooksOf(this).push(hook);
		return this;
	}

});

new Type('Type', Type);

// Default Types

var force = function(name, object, methods){
	var isType = (object != Object),
		prototype = object.prototype;

	if (isType) object = new Type(name, object);

	for (var i = 0, l = methods.length; i < l; i++){
		var key = methods[i],
			generic = object[key],
			proto = prototype[key];

		if (generic) generic.protect();

		if (isType && proto){
			delete prototype[key];
			prototype[key] = proto.protect();
		}
	}

	if (isType) object.implement(prototype);

	return force;
};

force('String', String, [
	'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
	'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase'
])('Array', Array, [
	'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
	'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'
])('Number', Number, [
	'toExponential', 'toFixed', 'toLocaleString', 'toPrecision'
])('Function', Function, [
	'apply', 'call', 'bind'
])('RegExp', RegExp, [
	'exec', 'test'
])('Object', Object, [
	'create', 'defineProperty', 'defineProperties', 'keys',
	'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames',
	'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen'
])('Date', Date, ['now']);

Object.extend = extend.overloadSetter();

Date.extend('now', function(){
	return +(new Date);
});

new Type('Boolean', Boolean);

// fixes NaN returning as Number

Number.prototype.$family = function(){
	return isFinite(this) ? 'number' : 'null';
}.hide();

// Number.random

Number.extend('random', function(min, max){
	return Math.floor(Math.random() * (max - min + 1) + min);
});

// forEach, each

var hasOwnProperty = Object.prototype.hasOwnProperty;
Object.extend('forEach', function(object, fn, bind){
	for (var key in object){
		if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object);
	}
});

Object.each = Object.forEach;

Array.implement({

	forEach: function(fn, bind){
		for (var i = 0, l = this.length; i < l; i++){
			if (i in this) fn.call(bind, this[i], i, this);
		}
	},

	each: function(fn, bind){
		Array.forEach(this, fn, bind);
		return this;
	}

});

// Array & Object cloning, Object merging and appending

var cloneOf = function(item){
	// mdb: try/catch used to find infinite recursion bug when unlink called
    // with data with a cycle
	//try {
	//if (item) {
    //   var s = item.toString().toLowerCase();
    //    if (s == '[object object]')
    //       console.log("mootools cloneOf " + item.toString());
    //}

        switch (typeOf(item)) {
            case 'array':
                return item.clone();
            case 'object':
                return Object.clone(item);
            default:
                return item;
        }
    //} catch (e) {
	//	console.log("mootools cloneOf e" + e);
	//		throw e;
  	//  }
};

Array.implement('clone', function(){
	var i = this.length, clone = new Array(i);
	while (i--) clone[i] = cloneOf(this[i]);
	return clone;
});

var mergeOne = function(source, key, current){
	switch (typeOf(current)){
		case 'object':
			if (typeOf(source[key]) == 'object') Object.merge(source[key], current);
			else source[key] = Object.clone(current);
		break;
		case 'array': source[key] = current.clone(); break;
		default: source[key] = current;
	}
	return source;
};

Object.extend({

	merge: function(source, k, v){
		if (typeOf(k) == 'string') return mergeOne(source, k, v);
		for (var i = 1, l = arguments.length; i < l; i++){
			var object = arguments[i];
			for (var key in object) mergeOne(source, key, object[key]);
		}
		return source;
	},

	clone: function(object){
		var clone = {};
		for (var key in object) clone[key] = cloneOf(object[key]);
		return clone;
	},

	append: function(original){
		for (var i = 1, l = arguments.length; i < l; i++){
			var extended = arguments[i] || {};
			for (var key in extended) original[key] = extended[key];
		}
		return original;
	}

});

// Object-less types

['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){
	new Type(name);
});

// Unique ID

var UID = Date.now();

String.extend('uniqueID', function(){
	return (UID++).toString(36);
});

//<1.2compat>

var Hash = this.Hash = new Type('Hash', function(object){
	if (typeOf(object) == 'hash') object = Object.clone(object.getClean());
	for (var key in object) this[key] = object[key];
	return this;
});

Hash.implement({

	forEach: function(fn, bind){
		Object.forEach(this, fn, bind);
	},

	getClean: function(){
		var clean = {};
		for (var key in this){
			if (this.hasOwnProperty(key)) clean[key] = this[key];
		}
		return clean;
	},

	getLength: function(){
		var length = 0;
		for (var key in this){
			if (this.hasOwnProperty(key)) length++;
		}
		return length;
	}

});

Hash.alias('each', 'forEach');

Object.type = Type.isObject;

var Native = this.Native = function(properties){
	return new Type(properties.name, properties.initialize);
};

Native.type = Type.type;

Native.implement = function(objects, methods){
	for (var i = 0; i < objects.length; i++) objects[i].implement(methods);
	return Native;
};

var arrayType = Array.type;
Array.type = function(item){
	return instanceOf(item, Array) || arrayType(item);
};

this.$A = function(item){
	return Array.from(item).slice();
};

this.$arguments = function(i){
	return function(){
		return arguments[i];
	};
};

this.$chk = function(obj){
	return !!(obj || obj === 0);
};

this.$clear = function(timer){
	clearTimeout(timer);
	clearInterval(timer);
	return null;
};

this.$defined = function(obj){
	return (obj != null);
};

this.$each = function(iterable, fn, bind){
	var type = typeOf(iterable);
	((type == 'arguments' || type == 'collection' || type == 'array' || type == 'elements') ? Array : Object).each(iterable, fn, bind);
};

this.$empty = function(){};

this.$extend = function(original, extended){
	return Object.append(original, extended);
};

this.$H = function(object){
	return new Hash(object);
};

this.$merge = function(){
	var args = Array.slice(arguments);
	args.unshift({});
	return Object.merge.apply(null, args);
};

this.$lambda = Function.from;
this.$mixin = Object.merge;
this.$random = Number.random;
this.$splat = Array.from;
this.$time = Date.now;

this.$type = function(object){
	var type = typeOf(object);
	if (type == 'elements') return 'array';
	return (type == 'null') ? false : type;
};

this.$unlink = function(object){
	switch (typeOf(object)){
		case 'object': return Object.clone(object);
		case 'array': return Array.clone(object);
		case 'hash': return new Hash(object);
		default: return object;
	}
};

//</1.2compat>

})();


/*
---

name: Array

description: Contains Array Prototypes like each, contains, and erase.

license: MIT-style license.

requires: Type

provides: Array

...
*/

Array.implement({

	/*<!ES5>*/
	every: function(fn, bind){
		for (var i = 0, l = this.length; i < l; i++){
			if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
		}
		return true;
	},

	filter: function(fn, bind){
		var results = [];
		for (var i = 0, l = this.length; i < l; i++){
			if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]);
		}
		return results;
	},

	indexOf: function(item, from){
		var len = this.length;
		for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
			if (this[i] === item) return i;
		}
		return -1;
	},

	map: function(fn, bind){
		var results = [];
		for (var i = 0, l = this.length; i < l; i++){
			if (i in this) results[i] = fn.call(bind, this[i], i, this);
		}
		return results;
	},

	some: function(fn, bind){
		for (var i = 0, l = this.length; i < l; i++){
			if ((i in this) && fn.call(bind, this[i], i, this)) return true;
		}
		return false;
	},
	/*</!ES5>*/

	clean: function(){
		return this.filter(function(item){
			return item != null;
		});
	},

	invoke: function(methodName){
		var args = Array.slice(arguments, 1);
		return this.map(function(item){
			return item[methodName].apply(item, args);
		});
	},

	associate: function(keys){
		var obj = {}, length = Math.min(this.length, keys.length);
		for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
		return obj;
	},

	link: function(object){
		var result = {};
		for (var i = 0, l = this.length; i < l; i++){
			for (var key in object){
				if (object[key](this[i])){
					result[key] = this[i];
					delete object[key];
					break;
				}
			}
		}
		return result;
	},

	contains: function(item, from){
		return this.indexOf(item, from) != -1;
	},

	append: function(array){
		this.push.apply(this, array);
		return this;
	},

	getLast: function(){
		return (this.length) ? this[this.length - 1] : null;
	},

	getRandom: function(){
		return (this.length) ? this[Number.random(0, this.length - 1)] : null;
	},

	include: function(item){
		if (!this.contains(item)) this.push(item);
		return this;
	},

	combine: function(array){
		for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
		return this;
	},

	erase: function(item){
		for (var i = this.length; i--;){
			if (this[i] === item) this.splice(i, 1);
		}
		return this;
	},

	empty: function(){
		this.length = 0;
		return this;
	},

	flatten: function(){
		var array = [];
		for (var i = 0, l = this.length; i < l; i++){
			var type = typeOf(this[i]);
			if (type == 'null') continue;
			array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]);
		}
		return array;
	},

	pick: function(){
		for (var i = 0, l = this.length; i < l; i++){
			if (this[i] != null) return this[i];
		}
		return null;
	},

	hexToRgb: function(array){
		if (this.length != 3) return null;
		var rgb = this.map(function(value){
			if (value.length == 1) value += value;
			return value.toInt(16);
		});
		return (array) ? rgb : 'rgb(' + rgb + ')';
	},

	rgbToHex: function(array){
		if (this.length < 3) return null;
		if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
		var hex = [];
		for (var i = 0; i < 3; i++){
			var bit = (this[i] - 0).toString(16);
			hex.push((bit.length == 1) ? '0' + bit : bit);
		}
		return (array) ? hex : '#' + hex.join('');
	}

});

//<1.2compat>

Array.alias('extend', 'append');

var $pick = function(){
	return Array.from(arguments).pick();
};

//</1.2compat>


/*
---

name: String

description: Contains String Prototypes like camelCase, capitalize, test, and toInt.

license: MIT-style license.

requires: Type

provides: String

...
*/

String.implement({

	test: function(regex, params){
		return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this);
	},

	contains: function(string, separator){
		return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
	},

	trim: function(){
		return this.replace(/^\s+|\s+$/g, '');
	},

	clean: function(){
		return this.replace(/\s+/g, ' ').trim();
	},

	camelCase: function(){
		return this.replace(/-\D/g, function(match){
			return match.charAt(1).toUpperCase();
		});
	},

	hyphenate: function(){
		return this.replace(/[A-Z]/g, function(match){
			return ('-' + match.charAt(0).toLowerCase());
		});
	},

	capitalize: function(){
		return this.replace(/\b[a-z]/g, function(match){
			return match.toUpperCase();
		});
	},

	escapeRegExp: function(){
		return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
	},

	toInt: function(base){
		return parseInt(this, base || 10);
	},

	toFloat: function(){
		return parseFloat(this);
	},

	hexToRgb: function(array){
		var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
		return (hex) ? hex.slice(1).hexToRgb(array) : null;
	},

	rgbToHex: function(array){
		var rgb = this.match(/\d{1,3}/g);
		return (rgb) ? rgb.rgbToHex(array) : null;
	},

	substitute: function(object, regexp){
		return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
			if (match.charAt(0) == '\\') return match.slice(1);
			return (object[name] != null) ? object[name] : '';
		});
	}

});


/*
---

name: Number

description: Contains Number Prototypes like limit, round, times, and ceil.

license: MIT-style license.

requires: Type

provides: Number

...
*/

Number.implement({

	limit: function(min, max){
		return Math.min(max, Math.max(min, this));
	},

	round: function(precision){
		precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);
		return Math.round(this * precision) / precision;
	},

	times: function(fn, bind){
		for (var i = 0; i < this; i++) fn.call(bind, i, this);
	},

	toFloat: function(){
		return parseFloat(this);
	},

	toInt: function(base){
		return parseInt(this, base || 10);
	}

});

Number.alias('each', 'times');

(function(math){
	var methods = {};
	math.each(function(name){
		if (!Number[name]) methods[name] = function(){
			return Math[name].apply(null, [this].concat(Array.from(arguments)));
		};
	});
	Number.implement(methods);
})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);


/*
---

name: Function

description: Contains Function Prototypes like create, bind, pass, and delay.

license: MIT-style license.

requires: Type

provides: Function

...
*/

Function.extend({

	attempt: function(){
		for (var i = 0, l = arguments.length; i < l; i++){
			try {
				return arguments[i]();
			} catch (e){}
		}
		return null;
	}

});

Function.implement({

	attempt: function(args, bind){
		try {
			return this.apply(bind, Array.from(args));
		} catch (e){}
		
		return null;
	},

	/*<!ES5>*/
	bind: function(bind){
		var self = this,
			args = (arguments.length > 1) ? Array.slice(arguments, 1) : null;
		
		return function(){
			if (!args && !arguments.length) return self.call(bind);
			if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments)));
			return self.apply(bind, args || arguments);
		};
	},
	/*</!ES5>*/

	pass: function(args, bind){
		var self = this;
		if (args != null) args = Array.from(args);
		return function(){
			return self.apply(bind, args || arguments);
		};
	},

	delay: function(delay, bind, args){
		return setTimeout(this.pass((args == null ? [] : args), bind), delay);
	},

	periodical: function(periodical, bind, args){
		return setInterval(this.pass((args == null ? [] : args), bind), periodical);
	}

});

//<1.2compat>

delete Function.prototype.bind;

Function.implement({

	create: function(options){
		var self = this;
		options = options || {};
		return function(event){
			var args = options.arguments;
			args = (args != null) ? Array.from(args) : Array.slice(arguments, (options.event) ? 1 : 0);
			if (options.event) args = [event || window.event].extend(args);
			var returns = function(){
				return self.apply(options.bind || null, args);
			};
			if (options.delay) return setTimeout(returns, options.delay);
			if (options.periodical) return setInterval(returns, options.periodical);
			if (options.attempt) return Function.attempt(returns);
			return returns();
		};
	},

	bind: function(bind, args){
		var self = this;
		if (args != null) args = Array.from(args);
		return function(){
			return self.apply(bind, args || arguments);
		};
	},

	bindWithEvent: function(bind, args){
		var self = this;
		if (args != null) args = Array.from(args);
		return function(event){
			return self.apply(bind, (args == null) ? arguments : [event].concat(args));
		};
	},

	run: function(args, bind){
		return this.apply(bind, Array.from(args));
	}

});

var $try = Function.attempt;

//</1.2compat>


/*
---

name: Object

description: Object generic methods

license: MIT-style license.

requires: Type

provides: [Object, Hash]

...
*/

(function(){

var hasOwnProperty = Object.prototype.hasOwnProperty;

Object.extend({

	subset: function(object, keys){
		var results = {};
		for (var i = 0, l = keys.length; i < l; i++){
			var k = keys[i];
			if (k in object) results[k] = object[k];
		}
		return results;
	},

	map: function(object, fn, bind){
		var results = {};
		for (var key in object){
			if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object);
		}
		return results;
	},

	filter: function(object, fn, bind){
		var results = {};
		for (var key in object){
			var value = object[key];
			if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value;
		}
		return results;
	},

	every: function(object, fn, bind){
		for (var key in object){
			if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false;
		}
		return true;
	},

	some: function(object, fn, bind){
		for (var key in object){
			if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true;
		}
		return false;
	},

	keys: function(object){
		var keys = [];
		for (var key in object){
			if (hasOwnProperty.call(object, key)) keys.push(key);
		}
		return keys;
	},

	values: function(object){
		var values = [];
		for (var key in object){
			if (hasOwnProperty.call(object, key)) values.push(object[key]);
		}
		return values;
	},

	getLength: function(object){
		return Object.keys(object).length;
	},

	keyOf: function(object, value){
		for (var key in object){
			if (hasOwnProperty.call(object, key) && object[key] === value) return key;
		}
		return null;
	},

	contains: function(object, value){
		return Object.keyOf(object, value) != null;
	},

	toQueryString: function(object, base){
		var queryString = [];

		Object.each(object, function(value, key){
			if (base) key = base + '[' + key + ']';
			var result;
			switch (typeOf(value)){
				case 'object': result = Object.toQueryString(value, key); break;
				case 'array':
					var qs = {};
					value.each(function(val, i){
						qs[i] = val;
					});
					result = Object.toQueryString(qs, key);
				break;
				default: result = key + '=' + encodeURIComponent(value);
			}
			if (value != null) queryString.push(result);
		});

		return queryString.join('&');
	}

});

})();

//<1.2compat>

Hash.implement({

	has: Object.prototype.hasOwnProperty,

	keyOf: function(value){
		return Object.keyOf(this, value);
	},

	hasValue: function(value){
		return Object.contains(this, value);
	},

	extend: function(properties){
		Hash.each(properties || {}, function(value, key){
			Hash.set(this, key, value);
		}, this);
		return this;
	},

	combine: function(properties){
		Hash.each(properties || {}, function(value, key){
			Hash.include(this, key, value);
		}, this);
		return this;
	},

	erase: function(key){
		if (this.hasOwnProperty(key)) delete this[key];
		return this;
	},

	get: function(key){
		return (this.hasOwnProperty(key)) ? this[key] : null;
	},

	set: function(key, value){
		if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
		return this;
	},

	empty: function(){
		Hash.each(this, function(value, key){
			delete this[key];
		}, this);
		return this;
	},

	include: function(key, value){
		if (this[key] == null) this[key] = value;
		return this;
	},

	map: function(fn, bind){
		return new Hash(Object.map(this, fn, bind));
	},

	filter: function(fn, bind){
		return new Hash(Object.filter(this, fn, bind));
	},

	every: function(fn, bind){
		return Object.every(this, fn, bind);
	},

	some: function(fn, bind){
		return Object.some(this, fn, bind);
	},

	getKeys: function(){
		return Object.keys(this);
	},

	getValues: function(){
		return Object.values(this);
	},

	toQueryString: function(base){
		return Object.toQueryString(this, base);
	}

});

Hash.extend = Object.append;

Hash.alias({indexOf: 'keyOf', contains: 'hasValue'});

//</1.2compat>


/*
---

name: Browser

description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.

license: MIT-style license.

requires: [Array, Function, Number, String]

provides: [Browser, Window, Document]

...
*/

(function(){

var document = this.document;
var window = document.window = this;

var UID = 1;

this.$uid = (window.ActiveXObject) ? function(item){
	return (item.uid || (item.uid = [UID++]))[0];
} : function(item){
	return item.uid || (item.uid = UID++);
};

$uid(window);
$uid(document);

var ua = navigator.userAgent.toLowerCase(),
	platform = navigator.platform.toLowerCase(),
	UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0],
	mode = UA[1] == 'ie' && document.documentMode;

var Browser = this.Browser = {

	extend: Function.prototype.extend,

	name: (UA[1] == 'version') ? UA[3] : UA[1],

	version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),

	Platform: {
		name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]
	},

	Features: {
		xpath: !!(document.evaluate),
		air: !!(window.runtime),
		query: !!(document.querySelector),
		json: !!(window.JSON)
	},

	Plugins: {}

};

Browser[Browser.name] = true;
Browser[Browser.name + parseInt(Browser.version, 10)] = true;
Browser.Platform[Browser.Platform.name] = true;

// Request

Browser.Request = (function(){

	var XMLHTTP = function(){
		return new XMLHttpRequest();
	};

	var MSXML2 = function(){
		return new ActiveXObject('MSXML2.XMLHTTP');
	};

	var MSXML = function(){
		return new ActiveXObject('Microsoft.XMLHTTP');
	};

	return Function.attempt(function(){
		XMLHTTP();
		return XMLHTTP;
	}, function(){
		MSXML2();
		return MSXML2;
	}, function(){
		MSXML();
		return MSXML;
	});

})();

Browser.Features.xhr = !!(Browser.Request);

// Flash detection

var version = (Function.attempt(function(){
	return navigator.plugins['Shockwave Flash'].description;
}, function(){
	return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
}) || '0 r0').match(/\d+/g);

Browser.Plugins.Flash = {
	version: Number(version[0] || '0.' + version[1]) || 0,
	build: Number(version[2]) || 0
};

// String scripts

Browser.exec = function(text){
	if (!text) return text;
	if (window.execScript){
		window.execScript(text);
	} else {
		var script = document.createElement('script');
		script.setAttribute('type', 'text/javascript');
		script.text = text;
		document.head.appendChild(script);
		document.head.removeChild(script);
	}
	return text;
};

String.implement('stripScripts', function(exec){
	var scripts = '';
	var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
		scripts += code + '\n';
		return '';
	});
	if (exec === true) Browser.exec(scripts);
	else if (typeOf(exec) == 'function') exec(scripts, text);
	return text;
});

// Window, Document

Browser.extend({
	Document: this.Document,
	Window: this.Window,
	Element: this.Element,
	Event: this.Event
});

this.Window = this.$constructor = new Type('Window', function(){});

this.$family = Function.from('window').hide();

Window.mirror(function(name, method){
	window[name] = method;
});

this.Document = document.$constructor = new Type('Document', function(){});

document.$family = Function.from('document').hide();

Document.mirror(function(name, method){
	document[name] = method;
});

document.html = document.documentElement;
if (!document.head) document.head = document.getElementsByTagName('head')[0];

if (document.execCommand) try {
	document.execCommand("BackgroundImageCache", false, true);
} catch (e){}

/*<ltIE9>*/
if (this.attachEvent && !this.addEventListener){
	var unloadEvent = function(){
		this.detachEvent('onunload', unloadEvent);
		document.head = document.html = document.window = null;
	};
	this.attachEvent('onunload', unloadEvent);
}

// IE fails on collections and <select>.options (refers to <select>)
var arrayFrom = Array.from;
try {
	arrayFrom(document.html.childNodes);
} catch(e){
	Array.from = function(item){
		if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){
			var i = item.length, array = new Array(i);
			while (i--) array[i] = item[i];
			return array;
		}
		return arrayFrom(item);
	};

	var prototype = Array.prototype,
		slice = prototype.slice;
	['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){
		var method = prototype[name];
		Array[name] = function(item){
			return method.apply(Array.from(item), slice.call(arguments, 1));
		};
	});
}
/*</ltIE9>*/

//<1.2compat>

if (Browser.Platform.ios) Browser.Platform.ipod = true;

Browser.Engine = {};

var setEngine = function(name, version){
	Browser.Engine.name = name;
	Browser.Engine[name + version] = true;
	Browser.Engine.version = version;
};

if (Browser.ie){
	Browser.Engine.trident = true;

	switch (Browser.version){
		case 6: setEngine('trident', 4); break;
		case 7: setEngine('trident', 5); break;
		case 8: setEngine('trident', 6);
	}
}

if (Browser.firefox){
	Browser.Engine.gecko = true;

	if (Browser.version >= 3) setEngine('gecko', 19);
	else setEngine('gecko', 18);
}

if (Browser.safari || Browser.chrome){
	Browser.Engine.webkit = true;

	switch (Browser.version){
		case 2: setEngine('webkit', 419); break;
		case 3: setEngine('webkit', 420); break;
		case 4: setEngine('webkit', 525);
	}
}

if (Browser.opera){
	Browser.Engine.presto = true;

	if (Browser.version >= 9.6) setEngine('presto', 960);
	else if (Browser.version >= 9.5) setEngine('presto', 950);
	else setEngine('presto', 925);
}

if (Browser.name == 'unknown'){
	switch ((ua.match(/(?:webkit|khtml|gecko)/) || [])[0]){
		case 'webkit':
		case 'khtml':
			Browser.Engine.webkit = true;
		break;
		case 'gecko':
			Browser.Engine.gecko = true;
	}
}

this.$exec = Browser.exec;

//</1.2compat>

})();


/*
---

name: Event

description: Contains the Event Class, to make the event object cross-browser.

license: MIT-style license.

requires: [Window, Document, Array, Function, String, Object]

provides: Event

...
*/

var Event = new Type('Event', function(event, win){
	if (!win) win = window;
	var doc = win.document;
	event = event || win.event;
	if (event.$extended) return event;
	this.$extended = true;
	var type = event.type,
		target = event.target || event.srcElement,
		page = {},
		client = {},
		related = null,
		rightClick, wheel, code, key;
	while (target && target.nodeType == 3) target = target.parentNode;

	if (type.indexOf('key') != -1){
		code = event.which || event.keyCode;
		key = Object.keyOf(Event.Keys, code);
		if (type == 'keydown'){
			var fKey = code - 111;
			if (fKey > 0 && fKey < 13) key = 'f' + fKey;
		}
		if (!key) key = String.fromCharCode(code).toLowerCase();
	} else if ((/click|mouse|menu/i).test(type)){
		doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
		page = {
			x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
			y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
		};
		client = {
			x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
			y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
		};
		if ((/DOMMouseScroll|mousewheel/).test(type)){
			wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
		}
		rightClick = (event.which == 3) || (event.button == 2);
		if ((/over|out/).test(type)){
			related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
			var testRelated = function(){
				while (related && related.nodeType == 3) related = related.parentNode;
				return true;
			};
			var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated();
			related = (hasRelated) ? related : null;
		}
	} else if ((/gesture|touch/i).test(type)){
		this.rotation = event.rotation;
		this.scale = event.scale;
		this.targetTouches = event.targetTouches;
		this.changedTouches = event.changedTouches;
		var touches = this.touches = event.touches;
		if (touches && touches[0]){
			var touch = touches[0];
			page = {x: touch.pageX, y: touch.pageY};
			client = {x: touch.clientX, y: touch.clientY};
		}
	}

	return Object.append(this, {
		event: event,
		type: type,

		page: page,
		client: client,
		rightClick: rightClick,

		wheel: wheel,

		relatedTarget: document.id(related),
		target: document.id(target),

		code: code,
		key: key,

		shift: event.shiftKey,
		control: event.ctrlKey,
		alt: event.altKey,
		meta: event.metaKey
	});
});

Event.Keys = {
	'enter': 13,
	'up': 38,
	'down': 40,
	'left': 37,
	'right': 39,
	'esc': 27,
	'space': 32,
	'backspace': 8,
	'tab': 9,
	'delete': 46
};

//<1.2compat>

Event.Keys = new Hash(Event.Keys);

//</1.2compat>

Event.implement({

	stop: function(){
		return this.stopPropagation().preventDefault();
	},

	stopPropagation: function(){
		if (this.event.stopPropagation) this.event.stopPropagation();
		else this.event.cancelBubble = true;
		return this;
	},

	preventDefault: function(){
		if (this.event.preventDefault) this.event.preventDefault();
		else this.event.returnValue = false;
		return this;
	}

});


/*
---

name: Class

description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.

license: MIT-style license.

requires: [Array, String, Function, Number]

provides: Class

...
*/

(function(){

var Class = this.Class = new Type('Class', function(params){
	if (instanceOf(params, Function)) params = {initialize: params};

	var newClass = function(){
		reset(this);
		if (newClass.$prototyping) return this;
		this.$caller = null;
		var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
		this.$caller = this.caller = null;
		return value;
	}.extend(this).implement(params);

	newClass.$constructor = Class;
	newClass.prototype.$constructor = newClass;
	newClass.prototype.parent = parent;

	return newClass;
});

var parent = function(){
	if (!this.$caller) throw new Error('The method "parent" cannot be called.');
	var name = this.$caller.$name,
		parent = this.$caller.$owner.parent,
		previous = (parent) ? parent.prototype[name] : null;
	if (!previous) throw new Error('The method "' + name + '" has no parent.');
	return previous.apply(this, arguments);
};

var reset = function(object){
	for (var key in object){
		var value = object[key];
		switch (typeOf(value)){
			case 'object':
				var F = function(){};
				F.prototype = value;
				object[key] = reset(new F);
			break;
			case 'array': object[key] = value.clone(); break;
		}
	}
	return object;
};

var wrap = function(self, key, method){
	if (method.$origin) method = method.$origin;
	var wrapper = function(){
		if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
		var caller = this.caller, current = this.$caller;
		this.caller = current; this.$caller = wrapper;
		var result = method.apply(this, arguments);
		this.$caller = current; this.caller = caller;
		return result;
	}.extend({$owner: self, $origin: method, $name: key});
	return wrapper;
};

var implement = function(key, value, retain){
	if (Class.Mutators.hasOwnProperty(key)){
		value = Class.Mutators[key].call(this, value);
		if (value == null) return this;
	}

	if (typeOf(value) == 'function'){
		if (value.$hidden) return this;
		this.prototype[key] = (retain) ? value : wrap(this, key, value);
	} else {
		Object.merge(this.prototype, key, value);
	}

	return this;
};

var getInstance = function(klass){
	klass.$prototyping = true;
	var proto = new klass;
	delete klass.$prototyping;
	return proto;
};

Class.implement('implement', implement.overloadSetter());

Class.Mutators = {

	Extends: function(parent){
		this.parent = parent;
		this.prototype = getInstance(parent);
	},

	Implements: function(items){
		Array.from(items).each(function(item){
			var instance = new item;
			for (var key in instance) implement.call(this, key, instance[key], true);
		}, this);
	}
};

})();


/*
---

name: Class.Extras

description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.

license: MIT-style license.

requires: Class

provides: [Class.Extras, Chain, Events, Options]

...
*/

(function(){

this.Chain = new Class({

	$chain: [],

	chain: function(){
		this.$chain.append(Array.flatten(arguments));
		return this;
	},

	callChain: function(){
		return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
	},

	clearChain: function(){
		this.$chain.empty();
		return this;
	}

});

var removeOn = function(string){
	return string.replace(/^on([A-Z])/, function(full, first){
		return first.toLowerCase();
	});
};

this.Events = new Class({

	$events: {},

	addEvent: function(type, fn, internal){
		type = removeOn(type);

		/*<1.2compat>*/
		if (fn == $empty) return this;
		/*</1.2compat>*/

		this.$events[type] = (this.$events[type] || []).include(fn);
		if (internal) fn.internal = true;
		return this;
	},

	addEvents: function(events){
		for (var type in events) this.addEvent(type, events[type]);
		return this;
	},

	fireEvent: function(type, args, delay){
		type = removeOn(type);
		var events = this.$events[type];
		if (!events) return this;
		args = Array.from(args);
		events.each(function(fn){
			if (delay) fn.delay(delay, this, args);
			else fn.apply(this, args);
		}, this);
		return this;
	},
	
	removeEvent: function(type, fn){
		type = removeOn(type);
		var events = this.$events[type];
		if (events && !fn.internal){
			var index =  events.indexOf(fn);
			if (index != -1) delete events[index];
		}
		return this;
	},

	removeEvents: function(events){
		var type;
		if (typeOf(events) == 'object'){
			for (type in events) this.removeEvent(type, events[type]);
			return this;
		}
		if (events) events = removeOn(events);
		for (type in this.$events){
			if (events && events != type) continue;
			var fns = this.$events[type];
			for (var i = fns.length; i--;) if (i in fns){
				this.removeEvent(type, fns[i]);
			}
		}
		return this;
	}

});

this.Options = new Class({

	setOptions: function(){
		var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
		if (this.addEvent) for (var option in options){
			if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
			this.addEvent(option, options[option]);
			delete options[option];
		}
		return this;
	}

});

})();


/*
---
name: Slick.Parser
description: Standalone CSS3 Selector parser
provides: Slick.Parser
...
*/

;(function(){

var parsed,
	separatorIndex,
	combinatorIndex,
	reversed,
	cache = {},
	reverseCache = {},
	reUnescape = /\\/g;

var parse = function(expression, isReversed){
	if (expression == null) return null;
	if (expression.Slick === true) return expression;
	expression = ('' + expression).replace(/^\s+|\s+$/g, '');
	reversed = !!isReversed;
	var currentCache = (reversed) ? reverseCache : cache;
	if (currentCache[expression]) return currentCache[expression];
	parsed = {
		Slick: true,
		expressions: [],
		raw: expression,
		reverse: function(){
			return parse(this.raw, true);
		}
	};
	separatorIndex = -1;
	while (expression != (expression = expression.replace(regexp, parser)));
	parsed.length = parsed.expressions.length;
	return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed;
};

var reverseCombinator = function(combinator){
	if (combinator === '!') return ' ';
	else if (combinator === ' ') return '!';
	else if ((/^!/).test(combinator)) return combinator.replace(/^!/, '');
	else return '!' + combinator;
};

var reverse = function(expression){
	var expressions = expression.expressions;
	for (var i = 0; i < expressions.length; i++){
		var exp = expressions[i];
		var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)};

		for (var j = 0; j < exp.length; j++){
			var cexp = exp[j];
			if (!cexp.reverseCombinator) cexp.reverseCombinator = ' ';
			cexp.combinator = cexp.reverseCombinator;
			delete cexp.reverseCombinator;
		}

		exp.reverse().push(last);
	}
	return expression;
};

var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License
	return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){
		return '\\' + match;
	});
};

var regexp = new RegExp(
/*
#!/usr/bin/env ruby
puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'')
__END__
	"(?x)^(?:\
	  \\s* ( , ) \\s*               # Separator          \n\
	| \\s* ( <combinator>+ ) \\s*   # Combinator         \n\
	|      ( \\s+ )                 # CombinatorChildren \n\
	|      ( <unicode>+ | \\* )     # Tag                \n\
	| \\#  ( <unicode>+       )     # ID                 \n\
	| \\.  ( <unicode>+       )     # ClassName          \n\
	|                               # Attribute          \n\
	\\[  \
		\\s* (<unicode1>+)  (?:  \
			\\s* ([*^$!~|]?=)  (?:  \
				\\s* (?:\
					([\"']?)(.*?)\\9 \
				)\
			)  \
		)?  \\s*  \
	\\](?!\\]) \n\
	|   :+ ( <unicode>+ )(?:\
	\\( (?:\
		(?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\
	) \\)\
	)?\
	)"
*/
	"^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)"
	.replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']')
	.replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
	.replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
);

function parser(
	rawMatch,

	separator,
	combinator,
	combinatorChildren,

	tagName,
	id,
	className,

	attributeKey,
	attributeOperator,
	attributeQuote,
	attributeValue,

	pseudoMarker,
	pseudoClass,
	pseudoQuote,
	pseudoClassQuotedValue,
	pseudoClassValue
){
	if (separator || separatorIndex === -1){
		parsed.expressions[++separatorIndex] = [];
		combinatorIndex = -1;
		if (separator) return '';
	}

	if (combinator || combinatorChildren || combinatorIndex === -1){
		combinator = combinator || ' ';
		var currentSeparator = parsed.expressions[separatorIndex];
		if (reversed && currentSeparator[combinatorIndex])
			currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator);
		currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'};
	}

	var currentParsed = parsed.expressions[separatorIndex][combinatorIndex];

	if (tagName){
		currentParsed.tag = tagName.replace(reUnescape, '');

	} else if (id){
		currentParsed.id = id.replace(reUnescape, '');

	} else if (className){
		className = className.replace(reUnescape, '');

		if (!currentParsed.classList) currentParsed.classList = [];
		if (!currentParsed.classes) currentParsed.classes = [];
		currentParsed.classList.push(className);
		currentParsed.classes.push({
			value: className,
			regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)')
		});

	} else if (pseudoClass){
		pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue;
		pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null;

		if (!currentParsed.pseudos) currentParsed.pseudos = [];
		currentParsed.pseudos.push({
			key: pseudoClass.replace(reUnescape, ''),
			value: pseudoClassValue,
			type: pseudoMarker.length == 1 ? 'class' : 'element'
		});

	} else if (attributeKey){
		attributeKey = attributeKey.replace(reUnescape, '');
		attributeValue = (attributeValue || '').replace(reUnescape, '');

		var test, regexp;

		switch (attributeOperator){
			case '^=' : regexp = new RegExp(       '^'+ escapeRegExp(attributeValue)            ); break;
			case '$=' : regexp = new RegExp(            escapeRegExp(attributeValue) +'$'       ); break;
			case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break;
			case '|=' : regexp = new RegExp(       '^'+ escapeRegExp(attributeValue) +'(-|$)'   ); break;
			case  '=' : test = function(value){
				return attributeValue == value;
			}; break;
			case '*=' : test = function(value){
				return value && value.indexOf(attributeValue) > -1;
			}; break;
			case '!=' : test = function(value){
				return attributeValue != value;
			}; break;
			default   : test = function(value){
				return !!value;
			};
		}

		if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){
			return false;
		};

		if (!test) test = function(value){
			return value && regexp.test(value);
		};

		if (!currentParsed.attributes) currentParsed.attributes = [];
		currentParsed.attributes.push({
			key: attributeKey,
			operator: attributeOperator,
			value: attributeValue,
			test: test
		});

	}

	return '';
};

// Slick NS

var Slick = (this.Slick || {});

Slick.parse = function(expression){
	return parse(expression);
};

Slick.escapeRegExp = escapeRegExp;

if (!this.Slick) this.Slick = Slick;

}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);


/*
---
name: Slick.Finder
description: The new, superfast css selector engine.
provides: Slick.Finder
requires: Slick.Parser
...
*/

;(function(){

var local = {},
	featuresCache = {},
	toString = Object.prototype.toString;

// Feature / Bug detection

local.isNativeCode = function(fn){
	return (/\{\s*\[native code\]\s*\}/).test('' + fn);
};

local.isXML = function(document){
	return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') ||
	(document.nodeType == 9 && document.documentElement.nodeName != 'HTML');
};

local.setDocument = function(document){

	// convert elements / window arguments to document. if document cannot be extrapolated, the function returns.
	var nodeType = document.nodeType;
	if (nodeType == 9); // document
	else if (nodeType) document = document.ownerDocument; // node
	else if (document.navigator) document = document.document; // window
	else return;

	// check if it's the old document

	if (this.document === document) return;
	this.document = document;

	// check if we have done feature detection on this document before

	var root = document.documentElement,
		rootUid = this.getUIDXML(root),
		features = featuresCache[rootUid],
		feature;

	if (features){
		for (feature in features){
			this[feature] = features[feature];
		}
		return;
	}

	features = featuresCache[rootUid] = {};

	features.root = root;
	features.isXMLDocument = this.isXML(document);

	features.brokenStarGEBTN
	= features.starSelectsClosedQSA
	= features.idGetsName
	= features.brokenMixedCaseQSA
	= features.brokenGEBCN
	= features.brokenCheckedQSA
	= features.brokenEmptyAttributeQSA
	= features.isHTMLDocument
	= features.nativeMatchesSelector
	= false;

	var starSelectsClosed, starSelectsComments,
		brokenSecondClassNameGEBCN, cachedGetElementsByClassName,
		brokenFormAttributeGetter;

	var selected, id = 'slick_uniqueid';
	var testNode = document.createElement('div');
	
	var testRoot = document.body || document.getElementsByTagName('body')[0] || root;
	testRoot.appendChild(testNode);

	// on non-HTML documents innerHTML and getElementsById doesnt work properly
	try {
		testNode.innerHTML = '<a id="'+id+'"></a>';
		features.isHTMLDocument = !!document.getElementById(id);
	} catch(e){};

	if (features.isHTMLDocument){

		testNode.style.display = 'none';

		// IE returns comment nodes for getElementsByTagName('*') for some documents
		testNode.appendChild(document.createComment(''));
		starSelectsComments = (testNode.getElementsByTagName('*').length > 1);

		// IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents
		try {
			testNode.innerHTML = 'foo</foo>';
			selected = testNode.getElementsByTagName('*');
			starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
		} catch(e){};

		features.brokenStarGEBTN = starSelectsComments || starSelectsClosed;

		// IE returns elements with the name instead of just id for getElementsById for some documents
		try {
			testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>';
			features.idGetsName = document.getElementById(id) === testNode.firstChild;
		} catch(e){};

		if (testNode.getElementsByClassName){

			// Safari 3.2 getElementsByClassName caches results
			try {
				testNode.innerHTML = '<a class="f"></a><a class="b"></a>';
				testNode.getElementsByClassName('b').length;
				testNode.firstChild.className = 'b';
				cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2);
			} catch(e){};

			// Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one
			try {
				testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>';
				brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2);
			} catch(e){};

			features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN;
		}
		
		if (testNode.querySelectorAll){
			// IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents
			try {
				testNode.innerHTML = 'foo</foo>';
				selected = testNode.querySelectorAll('*');
				features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
			} catch(e){};

			// Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode
			try {
				testNode.innerHTML = '<a class="MiX"></a>';
				features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length;
			} catch(e){};

			// Webkit and Opera dont return selected options on querySelectorAll
			try {
				testNode.innerHTML = '<select><option selected="selected">a</option></select>';
				features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0);
			} catch(e){};

			// IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll
			try {
				testNode.innerHTML = '<a class=""></a>';
				features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0);
			} catch(e){};

		}

		// IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input
		try {
			testNode.innerHTML = '<form action="s"><input id="action"/></form>';
			brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's');
		} catch(e){};

		// native matchesSelector function

		features.nativeMatchesSelector = root.matchesSelector || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector;
		if (features.nativeMatchesSelector) try {
			// if matchesSelector trows errors on incorrect sintaxes we can use it
			features.nativeMatchesSelector.call(root, ':slick');
			features.nativeMatchesSelector = null;
		} catch(e){};

	}

	try {
		root.slick_expando = 1;
		delete root.slick_expando;
		features.getUID = this.getUIDHTML;
	} catch(e) {
		features.getUID = this.getUIDXML;
	}

	testRoot.removeChild(testNode);
	testNode = selected = testRoot = null;

	// getAttribute

	features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){
		var method = this.attributeGetters[name];
		if (method) return method.call(node);
		var attributeNode = node.getAttributeNode(name);
		return (attributeNode) ? attributeNode.nodeValue : null;
	} : function(node, name){
		var method = this.attributeGetters[name];
		return (method) ? method.call(node) : node.getAttribute(name);
	};

	// hasAttribute

	features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) {
		return node.hasAttribute(attribute);
	} : function(node, attribute) {
		node = node.getAttributeNode(attribute);
		return !!(node && (node.specified || node.nodeValue));
	};

	// contains
	// FIXME: Add specs: local.contains should be different for xml and html documents?
	features.contains = (root && this.isNativeCode(root.contains)) ? function(context, node){
		return context.contains(node);
	} : (root && root.compareDocumentPosition) ? function(context, node){
		return context === node || !!(context.compareDocumentPosition(node) & 16);
	} : function(context, node){
		if (node) do {
			if (node === context) return true;
		} while ((node = node.parentNode));
		return false;
	};

	// document order sorting
	// credits to Sizzle (http://sizzlejs.com/)

	features.documentSorter = (root.compareDocumentPosition) ? function(a, b){
		if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0;
		return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
	} : ('sourceIndex' in root) ? function(a, b){
		if (!a.sourceIndex || !b.sourceIndex) return 0;
		return a.sourceIndex - b.sourceIndex;
	} : (document.createRange) ? function(a, b){
		if (!a.ownerDocument || !b.ownerDocument) return 0;
		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
		aRange.setStart(a, 0);
		aRange.setEnd(a, 0);
		bRange.setStart(b, 0);
		bRange.setEnd(b, 0);
		return aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
	} : null ;

	root = null;

	for (feature in features){
		this[feature] = features[feature];
	}
};

// Main Method

var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/,
	reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/,
	qsaFailExpCache = {};

local.search = function(context, expression, append, first){

	var found = this.found = (first) ? null : (append || []);
	
	if (!context) return found;
	else if (context.navigator) context = context.document; // Convert the node from a window to a document
	else if (!context.nodeType) return found;

	// setup

	var parsed, i,
		uniques = this.uniques = {},
		hasOthers = !!(append && append.length),
		contextIsDocument = (context.nodeType == 9);

	if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context);

	// avoid duplicating items already in the append array
	if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true;

	// expression checks

	if (typeof expression == 'string'){ // expression is a string

		/*<simple-selectors-override>*/
		var simpleSelector = expression.match(reSimpleSelector);
		simpleSelectors: if (simpleSelector) {

			var symbol = simpleSelector[1],
				name = simpleSelector[2],
				node, nodes;

			if (!symbol){

				if (name == '*' && this.brokenStarGEBTN) break simpleSelectors;
				nodes = context.getElementsByTagName(name);
				if (first) return nodes[0] || null;
				for (i = 0; node = nodes[i++];){
					if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
				}

			} else if (symbol == '#'){

				if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors;
				node = context.getElementById(name);
				if (!node) return found;
				if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors;
				if (first) return node || null;
				if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);

			} else if (symbol == '.'){

				if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors;
				if (context.getElementsByClassName && !this.brokenGEBCN){
					nodes = context.getElementsByClassName(name);
					if (first) return nodes[0] || null;
					for (i = 0; node = nodes[i++];){
						if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
					}
				} else {
					var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)');
					nodes = context.getElementsByTagName('*');
					for (i = 0; node = nodes[i++];){
						className = node.className;
						if (!(className && matchClass.test(className))) continue;
						if (first) return node;
						if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
					}
				}

			}

			if (hasOthers) this.sort(found);
			return (first) ? null : found;

		}
		/*</simple-selectors-override>*/

		/*<query-selector-override>*/
		querySelector: if (context.querySelectorAll) {

			if (!this.isHTMLDocument
				|| qsaFailExpCache[expression]
				//TODO: only skip when expression is actually mixed case
				|| this.brokenMixedCaseQSA
				|| (this.brokenCheckedQSA && expression.indexOf(':checked') > -1)
				|| (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression))
				|| (!contextIsDocument //Abort when !contextIsDocument and...
					//  there are multiple expressions in the selector
					//  since we currently only fix non-document rooted QSA for single expression selectors
					&& expression.indexOf(',') > -1
				)
				|| Slick.disableQSA
			) break querySelector;

			var _expression = expression, _context = context;
			if (!contextIsDocument){
				// non-document rooted QSA
				// credits to Andrew Dupont
				var currentId = _context.getAttribute('id'), slickid = 'slickid__';
				_context.setAttribute('id', slickid);
				_expression = '#' + slickid + ' ' + _expression;
				context = _context.parentNode;
			}

			try {
				if (first) return context.querySelector(_expression) || null;
				else nodes = context.querySelectorAll(_expression);
			} catch(e) {
				qsaFailExpCache[expression] = 1;
				break querySelector;
			} finally {
				if (!contextIsDocument){
					if (currentId) _context.setAttribute('id', currentId);
					else _context.removeAttribute('id');
					context = _context;
				}
			}

			if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){
				if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node);
			} else for (i = 0; node = nodes[i++];){
				if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
			}

			if (hasOthers) this.sort(found);
			return found;

		}
		/*</query-selector-override>*/

		parsed = this.Slick.parse(expression);
		if (!parsed.length) return found;
	} else if (expression == null){ // there is no expression
		return found;
	} else if (expression.Slick){ // expression is a parsed Slick object
		parsed = expression;
	} else if (this.contains(context.documentElement || context, expression)){ // expression is a node
		(found) ? found.push(expression) : found = expression;
		return found;
	} else { // other junk
		return found;
	}

	/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/

	// cache elements for the nth selectors

	this.posNTH = {};
	this.posNTHLast = {};
	this.posNTHType = {};
	this.posNTHTypeLast = {};

	/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/

	// if append is null and there is only a single selector with one expression use pushArray, else use pushUID
	this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID;

	if (found == null) found = [];

	// default engine

	var j, m, n;
	var combinator, tag, id, classList, classes, attributes, pseudos;
	var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions;

	search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){

		combinator = 'combinator:' + currentBit.combinator;
		if (!this[combinator]) continue search;

		tag        = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase();
		id         = currentBit.id;
		classList  = currentBit.classList;
		classes    = currentBit.classes;
		attributes = currentBit.attributes;
		pseudos    = currentBit.pseudos;
		lastBit    = (j === (currentExpression.length - 1));

		this.bitUniques = {};

		if (lastBit){
			this.uniques = uniques;
			this.found = found;
		} else {
			this.uniques = {};
			this.found = [];
		}

		if (j === 0){
			this[combinator](context, tag, id, classes, attributes, pseudos, classList);
			if (first && lastBit && found.length) break search;
		} else {
			if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){
				this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
				if (found.length) break search;
			} else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
		}

		currentItems = this.found;
	}

	// should sort if there are nodes in append and if you pass multiple expressions.
	if (hasOthers || (parsed.expressions.length > 1)) this.sort(found);

	return (first) ? (found[0] || null) : found;
};

// Utils

local.uidx = 1;
local.uidk = 'slick-uniqueid';

local.getUIDXML = function(node){
	var uid = node.getAttribute(this.uidk);
	if (!uid){
		uid = this.uidx++;
		node.setAttribute(this.uidk, uid);
	}
	return uid;
};

local.getUIDHTML = function(node){
	return node.uniqueNumber || (node.uniqueNumber = this.uidx++);
};

// sort based on the setDocument documentSorter method.

local.sort = function(results){
	if (!this.documentSorter) return results;
	results.sort(this.documentSorter);
	return results;
};

/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/

local.cacheNTH = {};

local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;

local.parseNTHArgument = function(argument){
	var parsed = argument.match(this.matchNTH);
	if (!parsed) return false;
	var special = parsed[2] || false;
	var a = parsed[1] || 1;
	if (a == '-') a = -1;
	var b = +parsed[3] || 0;
	parsed =
		(special == 'n')	? {a: a, b: b} :
		(special == 'odd')	? {a: 2, b: 1} :
		(special == 'even')	? {a: 2, b: 0} : {a: 0, b: a};

	return (this.cacheNTH[argument] = parsed);
};

local.createNTHPseudo = function(child, sibling, positions, ofType){
	return function(node, argument){
		var uid = this.getUID(node);
		if (!this[positions][uid]){
			var parent = node.parentNode;
			if (!parent) return false;
			var el = parent[child], count = 1;
			if (ofType){
				var nodeName = node.nodeName;
				do {
					if (el.nodeName != nodeName) continue;
					this[positions][this.getUID(el)] = count++;
				} while ((el = el[sibling]));
			} else {
				do {
					if (el.nodeType != 1) continue;
					this[positions][this.getUID(el)] = count++;
				} while ((el = el[sibling]));
			}
		}
		argument = argument || 'n';
		var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument);
		if (!parsed) return false;
		var a = parsed.a, b = parsed.b, pos = this[positions][uid];
		if (a == 0) return b == pos;
		if (a > 0){
			if (pos < b) return false;
		} else {
			if (b < pos) return false;
		}
		return ((pos - b) % a) == 0;
	};
};

/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/

local.pushArray = function(node, tag, id, classes, attributes, pseudos){
	if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node);
};

local.pushUID = function(node, tag, id, classes, attributes, pseudos){
	var uid = this.getUID(node);
	if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){
		this.uniques[uid] = true;
		this.found.push(node);
	}
};

local.matchNode = function(node, selector){
	if (this.isHTMLDocument && this.nativeMatchesSelector){
		try {
			return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]'));
		} catch(matchError) {}
	}
	
	var parsed = this.Slick.parse(selector);
	if (!parsed) return true;

	// simple (single) selectors
	var expressions = parsed.expressions, reversedExpressions, simpleExpCounter = 0, i;
	for (i = 0; (currentExpression = expressions[i]); i++){
		if (currentExpression.length == 1){
			var exp = currentExpression[0];
			if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true;
			simpleExpCounter++;
		}
	}

	if (simpleExpCounter == parsed.length) return false;

	var nodes = this.search(this.document, parsed), item;
	for (i = 0; item = nodes[i++];){
		if (item === node) return true;
	}
	return false;
};

local.matchPseudo = function(node, name, argument){
	var pseudoName = 'pseudo:' + name;
	if (this[pseudoName]) return this[pseudoName](node, argument);
	var attribute = this.getAttribute(node, name);
	return (argument) ? argument == attribute : !!attribute;
};

local.matchSelector = function(node, tag, id, classes, attributes, pseudos){
	if (tag){
		var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase();
		if (tag == '*'){
			if (nodeName < '@') return false; // Fix for comment nodes and closed nodes
		} else {
			if (nodeName != tag) return false;
		}
	}

	if (id && node.getAttribute('id') != id) return false;

	var i, part, cls;
	if (classes) for (i = classes.length; i--;){
		cls = node.getAttribute('class') || node.className;
		if (!(cls && classes[i].regexp.test(cls))) return false;
	}
	if (attributes) for (i = attributes.length; i--;){
		part = attributes[i];
		if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false;
	}
	if (pseudos) for (i = pseudos.length; i--;){
		part = pseudos[i];
		if (!this.matchPseudo(node, part.key, part.value)) return false;
	}
	return true;
};

var combinators = {

	' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level

		var i, item, children;

		if (this.isHTMLDocument){
			getById: if (id){
				item = this.document.getElementById(id);
				if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){
					// all[id] returns all the elements with that name or id inside node
					// if theres just one it will return the element, else it will be a collection
					children = node.all[id];
					if (!children) return;
					if (!children[0]) children = [children];
					for (i = 0; item = children[i++];){
						var idNode = item.getAttributeNode('id');
						if (idNode && idNode.nodeValue == id){
							this.push(item, tag, null, classes, attributes, pseudos);
							break;
						}
					} 
					return;
				}
				if (!item){
					// if the context is in the dom we return, else we will try GEBTN, breaking the getById label
					if (this.contains(this.root, node)) return;
					else break getById;
				} else if (this.document !== node && !this.contains(node, item)) return;
				this.push(item, tag, null, classes, attributes, pseudos);
				return;
			}
			getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){
				children = node.getElementsByClassName(classList.join(' '));
				if (!(children && children.length)) break getByClass;
				for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos);
				return;
			}
		}
		getByTag: {
			children = node.getElementsByTagName(tag);
			if (!(children && children.length)) break getByTag;
			if (!this.brokenStarGEBTN) tag = null;
			for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos);
		}
	},

	'>': function(node, tag, id, classes, attributes, pseudos){ // direct children
		if ((node = node.firstChild)) do {
			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
		} while ((node = node.nextSibling));
	},

	'+': function(node, tag, id, classes, attributes, pseudos){ // next sibling
		while ((node = node.nextSibling)) if (node.nodeType == 1){
			this.push(node, tag, id, classes, attributes, pseudos);
			break;
		}
	},

	'^': function(node, tag, id, classes, attributes, pseudos){ // first child
		node = node.firstChild;
		if (node){
			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
			else this['combinator:+'](node, tag, id, classes, attributes, pseudos);
		}
	},

	'~': function(node, tag, id, classes, attributes, pseudos){ // next siblings
		while ((node = node.nextSibling)){
			if (node.nodeType != 1) continue;
			var uid = this.getUID(node);
			if (this.bitUniques[uid]) break;
			this.bitUniques[uid] = true;
			this.push(node, tag, id, classes, attributes, pseudos);
		}
	},

	'++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling
		this['combinator:+'](node, tag, id, classes, attributes, pseudos);
		this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
	},

	'~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings
		this['combinator:~'](node, tag, id, classes, attributes, pseudos);
		this['combinator:!~'](node, tag, id, classes, attributes, pseudos);
	},

	'!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document
		while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
	},

	'!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level)
		node = node.parentNode;
		if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
	},

	'!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling
		while ((node = node.previousSibling)) if (node.nodeType == 1){
			this.push(node, tag, id, classes, attributes, pseudos);
			break;
		}
	},

	'!^': function(node, tag, id, classes, attributes, pseudos){ // last child
		node = node.lastChild;
		if (node){
			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
			else this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
		}
	},

	'!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings
		while ((node = node.previousSibling)){
			if (node.nodeType != 1) continue;
			var uid = this.getUID(node);
			if (this.bitUniques[uid]) break;
			this.bitUniques[uid] = true;
			this.push(node, tag, id, classes, attributes, pseudos);
		}
	}

};

for (var c in combinators) local['combinator:' + c] = combinators[c];

var pseudos = {

	/*<pseudo-selectors>*/

	'empty': function(node){
		var child = node.firstChild;
		return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length;
	},

	'not': function(node, expression){
		return !this.matchNode(node, expression);
	},

	'contains': function(node, text){
		return (node.innerText || node.textContent || '').indexOf(text) > -1;
	},

	'first-child': function(node){
		while ((node = node.previousSibling)) if (node.nodeType == 1) return false;
		return true;
	},

	'last-child': function(node){
		while ((node = node.nextSibling)) if (node.nodeType == 1) return false;
		return true;
	},

	'only-child': function(node){
		var prev = node;
		while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false;
		var next = node;
		while ((next = next.nextSibling)) if (next.nodeType == 1) return false;
		return true;
	},

	/*<nth-pseudo-selectors>*/

	'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'),

	'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'),

	'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true),

	'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true),

	'index': function(node, index){
		return this['pseudo:nth-child'](node, '' + index + 1);
	},

	'even': function(node){
		return this['pseudo:nth-child'](node, '2n');
	},

	'odd': function(node){
		return this['pseudo:nth-child'](node, '2n+1');
	},

	/*</nth-pseudo-selectors>*/

	/*<of-type-pseudo-selectors>*/

	'first-of-type': function(node){
		var nodeName = node.nodeName;
		while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false;
		return true;
	},

	'last-of-type': function(node){
		var nodeName = node.nodeName;
		while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false;
		return true;
	},

	'only-of-type': function(node){
		var prev = node, nodeName = node.nodeName;
		while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false;
		var next = node;
		while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false;
		return true;
	},

	/*</of-type-pseudo-selectors>*/

	// custom pseudos

	'enabled': function(node){
		return !node.disabled;
	},

	'disabled': function(node){
		return node.disabled;
	},

	'checked': function(node){
		return node.checked || node.selected;
	},

	'focus': function(node){
		return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex'));
	},

	'root': function(node){
		return (node === this.root);
	},
	
	'selected': function(node){
		return node.selected;
	}

	/*</pseudo-selectors>*/
};

for (var p in pseudos) local['pseudo:' + p] = pseudos[p];

// attributes methods

local.attributeGetters = {

	'class': function(){
		return this.getAttribute('class') || this.className;
	},

	'for': function(){
		return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for');
	},

	'href': function(){
		return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href');
	},

	'style': function(){
		return (this.style) ? this.style.cssText : this.getAttribute('style');
	},
	
	'tabindex': function(){
		var attributeNode = this.getAttributeNode('tabindex');
		return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null;
	},

	'type': function(){
		return this.getAttribute('type');
	}

};

// Slick

var Slick = local.Slick = (this.Slick || {});

Slick.version = '1.1.5';

// Slick finder

Slick.search = function(context, expression, append){
	return local.search(context, expression, append);
};

Slick.find = function(context, expression){
	return local.search(context, expression, null, true);
};

// Slick containment checker

Slick.contains = function(container, node){
	local.setDocument(container);
	return local.contains(container, node);
};

// Slick attribute getter

Slick.getAttribute = function(node, name){
	return local.getAttribute(node, name);
};

// Slick matcher

Slick.match = function(node, selector){
	if (!(node && selector)) return false;
	if (!selector || selector === node) return true;
	local.setDocument(node);
	return local.matchNode(node, selector);
};

// Slick attribute accessor

Slick.defineAttributeGetter = function(name, fn){
	local.attributeGetters[name] = fn;
	return this;
};

Slick.lookupAttributeGetter = function(name){
	return local.attributeGetters[name];
};

// Slick pseudo accessor

Slick.definePseudo = function(name, fn){
	local['pseudo:' + name] = function(node, argument){
		return fn.call(node, argument);
	};
	return this;
};

Slick.lookupPseudo = function(name){
	var pseudo = local['pseudo:' + name];
	if (pseudo) return function(argument){
		return pseudo.call(this, argument);
	};
	return null;
};

// Slick overrides accessor

Slick.override = function(regexp, fn){
	local.override(regexp, fn);
	return this;
};

Slick.isXML = local.isXML;

Slick.uidOf = function(node){
	return local.getUIDHTML(node);
};

if (!this.Slick) this.Slick = Slick;

}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);


/*
---

name: Element

description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements.

license: MIT-style license.

requires: [Window, Document, Array, String, Function, Number, Slick.Parser, Slick.Finder]

provides: [Element, Elements, $, $$, Iframe, Selectors]

...
*/

var Element = function(tag, props){
	var konstructor = Element.Constructors[tag];
	if (konstructor) return konstructor(props);
	if (typeof tag != 'string') return document.id(tag).set(props);

	if (!props) props = {};

	if (!(/^[\w-]+$/).test(tag)){
		var parsed = Slick.parse(tag).expressions[0][0];
		tag = (parsed.tag == '*') ? 'div' : parsed.tag;
		if (parsed.id && props.id == null) props.id = parsed.id;

		var attributes = parsed.attributes;
		if (attributes) for (var i = 0, l = attributes.length; i < l; i++){
			var attr = attributes[i];
			if (props[attr.key] != null) continue;

			if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value;
			else if (!attr.value && !attr.operator) props[attr.key] = true;
		}

		if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' ');
	}

	return document.newElement(tag, props);
};

if (Browser.Element) Element.prototype = Browser.Element.prototype;

new Type('Element', Element).mirror(function(name){
	if (Array.prototype[name]) return;

	var obj = {};
	obj[name] = function(){
		var results = [], args = arguments, elements = true;
		for (var i = 0, l = this.length; i < l; i++){
			var element = this[i], result = results[i] = element[name].apply(element, args);
			elements = (elements && typeOf(result) == 'element');
		}
		return (elements) ? new Elements(results) : results;
	};

	Elements.implement(obj);
});

if (!Browser.Element){
	Element.parent = Object;

	Element.Prototype = {'$family': Function.from('element').hide()};

	Element.mirror(function(name, method){
		Element.Prototype[name] = method;
	});
}

Element.Constructors = {};

//<1.2compat>

Element.Constructors = new Hash;

//</1.2compat>

var IFrame = new Type('IFrame', function(){
	var params = Array.link(arguments, {
		properties: Type.isObject,
		iframe: function(obj){
			return (obj != null);
		}
	});

	var props = params.properties || {}, iframe;
	if (params.iframe) iframe = document.id(params.iframe);
	var onload = props.onload || function(){};
	delete props.onload;
	props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick();
	iframe = new Element(iframe || 'iframe', props);

	var onLoad = function(){
		onload.call(iframe.contentWindow);
	};

	if (window.frames[props.id]) onLoad();
	else iframe.addListener('load', onLoad);
	return iframe;
});

var Elements = this.Elements = function(nodes){
	if (nodes && nodes.length){
		var uniques = {}, node;
		for (var i = 0; node = nodes[i++];){
			var uid = Slick.uidOf(node);
			if (!uniques[uid]){
				uniques[uid] = true;
				this.push(node);
			}
		}
	}
};

Elements.prototype = {length: 0};
Elements.parent = Array;

new Type('Elements', Elements).implement({

	filter: function(filter, bind){
		if (!filter) return this;
		return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){
			return item.match(filter);
		} : filter, bind));
	}.protect(),

	push: function(){
		var length = this.length;
		for (var i = 0, l = arguments.length; i < l; i++){
			var item = document.id(arguments[i]);
			if (item) this[length++] = item;
		}
		return (this.length = length);
	}.protect(),

	unshift: function(){
		var items = [];
		for (var i = 0, l = arguments.length; i < l; i++){
			var item = document.id(arguments[i]);
			if (item) items.push(item);
		}
		return Array.prototype.unshift.apply(this, items);
	}.protect(),

	concat: function(){
		var newElements = new Elements(this);
		for (var i = 0, l = arguments.length; i < l; i++){
			var item = arguments[i];
			if (Type.isEnumerable(item)) newElements.append(item);
			else newElements.push(item);
		}
		return newElements;
	}.protect(),

	append: function(collection){
		for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]);
		return this;
	}.protect(),

	empty: function(){
		while (this.length) delete this[--this.length];
		return this;
	}.protect()

});

//<1.2compat>

Elements.alias('extend', 'append');

//</1.2compat>

(function(){

// FF, IE
var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2};

splice.call(object, 1, 1);
if (object[1] == 1) Elements.implement('splice', function(){
	var length = this.length;
	splice.apply(this, arguments);
	while (length >= this.length) delete this[length--];
	return this;
}.protect());

Elements.implement(Array.prototype);

Array.mirror(Elements);

/*<ltIE8>*/
var createElementAcceptsHTML;
try {
	var x = document.createElement('<input name=x>');
	createElementAcceptsHTML = (x.name == 'x');
} catch(e){}

var escapeQuotes = function(html){
	return ('' + html).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
};
/*</ltIE8>*/

Document.implement({

	newElement: function(tag, props){
		if (props && props.checked != null) props.defaultChecked = props.checked;
		/*<ltIE8>*/// Fix for readonly name and type properties in IE < 8
		if (createElementAcceptsHTML && props){
			tag = '<' + tag;
			if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"';
			if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"';
			tag += '>';
			delete props.name;
			delete props.type;
		}
		/*</ltIE8>*/
		return this.id(this.createElement(tag)).set(props);
	}

});

})();

Document.implement({

	newTextNode: function(text){
		return this.createTextNode(text);
	},

	getDocument: function(){
		return this;
	},

	getWindow: function(){
		return this.window;
	},

	id: (function(){

		var types = {

			string: function(id, nocash, doc){
				id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1'));
				return (id) ? types.element(id, nocash) : null;
			},

			element: function(el, nocash){
				$uid(el);
				if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){
					Object.append(el, Element.Prototype);
				}
				return el;
			},

			object: function(obj, nocash, doc){
				if (obj.toElement) return types.element(obj.toElement(doc), nocash);
				return null;
			}

		};

		types.textnode = types.whitespace = types.window = types.document = function(zero){
			return zero;
		};

		return function(el, nocash, doc){
			if (el && el.$family && el.uid) return el;
			var type = typeOf(el);
			return (types[type]) ? types[type](el, nocash, doc || document) : null;
		};

	})()

});

if (window.$ == null) Window.implement('$', function(el, nc){
	return document.id(el, nc, this.document);
});

Window.implement({

	getDocument: function(){
		return this.document;
	},

	getWindow: function(){
		return this;
	}

});

[Document, Element].invoke('implement', {

	getElements: function(expression){
		return Slick.search(this, expression, new Elements);
	},

	getElement: function(expression){
		return document.id(Slick.find(this, expression));
	}

});

//<1.2compat>

(function(search, find, match){

	this.Selectors = {};
	var pseudos = this.Selectors.Pseudo = new Hash();

	var addSlickPseudos = function(){
		for (var name in pseudos) if (pseudos.hasOwnProperty(name)){
			Slick.definePseudo(name, pseudos[name]);
			delete pseudos[name];
		}
	};

	Slick.search = function(context, expression, append){
		addSlickPseudos();
		return search.call(this, context, expression, append);
	};

	Slick.find = function(context, expression){
		addSlickPseudos();
		return find.call(this, context, expression);
	};

	Slick.match = function(node, selector){
		addSlickPseudos();
		return match.call(this, node, selector);
	};

})(Slick.search, Slick.find, Slick.match);

if (window.$$ == null) Window.implement('$$', function(selector){
	var elements = new Elements;
	if (arguments.length == 1 && typeof selector == 'string') return Slick.search(this.document, selector, elements);
	var args = Array.flatten(arguments);
	for (var i = 0, l = args.length; i < l; i++){
		var item = args[i];
		switch (typeOf(item)){
			case 'element': elements.push(item); break;
			case 'string': Slick.search(this.document, item, elements);
		}
	}
	return elements;
});

//</1.2compat>

if (window.$$ == null) Window.implement('$$', function(selector){
	if (arguments.length == 1){
		if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements);
		else if (Type.isEnumerable(selector)) return new Elements(selector);
	}
	return new Elements(arguments);
});

(function(){

var collected = {}, storage = {};
var formProps = {input: 'checked', option: 'selected', textarea: 'value'};

var get = function(uid){
	return (storage[uid] || (storage[uid] = {}));
};

var clean = function(item){
	var uid = item.uid;
	if (item.removeEvents) item.removeEvents();
	if (item.clearAttributes) item.clearAttributes();
	if (uid != null){
		delete collected[uid];
		delete storage[uid];
	}
	return item;
};

var camels = ['defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly',
	'rowSpan', 'tabIndex', 'useMap'
];
var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readOnly', 'multiple', 'selected',
	'noresize', 'defer', 'defaultChecked'
];
 var attributes = {
	'html': 'innerHTML',
	'class': 'className',
	'for': 'htmlFor',
	'text': (function(){
		var temp = document.createElement('div');
		return (temp.textContent == null) ? 'innerText' : 'textContent';
	})()
};
var readOnly = ['type'];
var expandos = ['value', 'defaultValue'];
var uriAttrs = /^(?:href|src|usemap)$/i;

bools = bools.associate(bools);
camels = camels.associate(camels.map(String.toLowerCase));
readOnly = readOnly.associate(readOnly);

Object.append(attributes, expandos.associate(expandos));

var inserters = {

	before: function(context, element){
		var parent = element.parentNode;
		if (parent) parent.insertBefore(context, element);
	},

	after: function(context, element){
		var parent = element.parentNode;
		if (parent) parent.insertBefore(context, element.nextSibling);
	},

	bottom: function(context, element){
		element.appendChild(context);
	},

	top: function(context, element){
		element.insertBefore(context, element.firstChild);
	}

};

inserters.inside = inserters.bottom;

//<1.2compat>

Object.each(inserters, function(inserter, where){

	where = where.capitalize();

	var methods = {};

	methods['inject' + where] = function(el){
		inserter(this, document.id(el, true));
		return this;
	};

	methods['grab' + where] = function(el){
		inserter(document.id(el, true), this);
		return this;
	};

	Element.implement(methods);

});

//</1.2compat>

var injectCombinator = function(expression, combinator){
	if (!expression) return combinator;

	expression = Object.clone(Slick.parse(expression));

	var expressions = expression.expressions;
	for (var i = expressions.length; i--;)
		expressions[i][0].combinator = combinator;

	return expression;
};

Element.implement({

	set: function(prop, value){
		var property = Element.Properties[prop];
		(property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value);
	}.overloadSetter(),

	get: function(prop){
		var property = Element.Properties[prop];
		return (property && property.get) ? property.get.apply(this) : this.getProperty(prop);
	}.overloadGetter(),

	erase: function(prop){
		var property = Element.Properties[prop];
		(property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
		return this;
	},

	setProperty: function(attribute, value){
		attribute = camels[attribute] || attribute;
		if (value == null) return this.removeProperty(attribute);
		var key = attributes[attribute];
		(key) ? this[key] = value :
			(bools[attribute]) ? this[attribute] = !!value : this.setAttribute(attribute, '' + value);
		return this;
	},

	setProperties: function(attributes){
		for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
		return this;
	},

	getProperty: function(attribute){
		attribute = camels[attribute] || attribute;
		var key = attributes[attribute] || readOnly[attribute];
		return (key) ? this[key] :
			(bools[attribute]) ? !!this[attribute] :
			(uriAttrs.test(attribute) ? this.getAttribute(attribute, 2) :
			(key = this.getAttributeNode(attribute)) ? key.nodeValue : null) || null;
	},

	getProperties: function(){
		var args = Array.from(arguments);
		return args.map(this.getProperty, this).associate(args);
	},

	removeProperty: function(attribute){
		attribute = camels[attribute] || attribute;
		var key = attributes[attribute];
		(key) ? this[key] = '' :
			(bools[attribute]) ? this[attribute] = false : this.removeAttribute(attribute);
		return this;
	},

	removeProperties: function(){
		Array.each(arguments, this.removeProperty, this);
		return this;
	},

	hasClass: function(className){
		return this.className.clean().contains(className, ' ');
	},

	addClass: function(className){
		if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
		return this;
	},

	removeClass: function(className){
		this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
		return this;
	},

	swapClass: function(toadd, toRemove) {
		addClass(toAdd);
		removeClass(toRemove);
	},

	toggleClass: function(className, force){
		if (force == null) force = !this.hasClass(className);
		return (force) ? this.addClass(className) : this.removeClass(className);
	},

	adopt: function(){
		var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length;
		if (length > 1) parent = fragment = document.createDocumentFragment();

		for (var i = 0; i < length; i++){
			var element = document.id(elements[i], true);
			if (element) parent.appendChild(element);
		}

		if (fragment) this.appendChild(fragment);

		return this;
	},

	appendText: function(text, where){
		return this.grab(this.getDocument().newTextNode(text), where);
	},

	grab: function(el, where){
		inserters[where || 'bottom'](document.id(el, true), this);
		return this;
	},

	inject: function(el, where){
		inserters[where || 'bottom'](this, document.id(el, true));
		return this;
	},

	replaces: function(el){
		el = document.id(el, true);
		el.parentNode.replaceChild(this, el);
		return this;
	},

	wraps: function(el, where){
		el = document.id(el, true);
		return this.replaces(el).grab(el, where);
	},

	getPrevious: function(expression){
		return document.id(Slick.find(this, injectCombinator(expression, '!~')));
	},

	getAllPrevious: function(expression){
		return Slick.search(this, injectCombinator(expression, '!~'), new Elements);
	},

	getNext: function(expression){
		return document.id(Slick.find(this, injectCombinator(expression, '~')));
	},

	getAllNext: function(expression){
		return Slick.search(this, injectCombinator(expression, '~'), new Elements);
	},

	getFirst: function(expression){
		return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]);
	},

	getLast: function(expression){
		return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast());
	},

	getParent: function(expression){
		return document.id(Slick.find(this, injectCombinator(expression, '!')));
	},

	getParents: function(expression){
		return Slick.search(this, injectCombinator(expression, '!'), new Elements);
	},

	getSiblings: function(expression){
		return Slick.search(this, injectCombinator(expression, '~~'), new Elements);
	},

	getChildren: function(expression){
		return Slick.search(this, injectCombinator(expression, '>'), new Elements);
	},

	getWindow: function(){
		return this.ownerDocument.window;
	},

	getDocument: function(){
		return this.ownerDocument;
	},

	getElementById: function(id){
		return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1')));
	},

	getSelected: function(){
		this.selectedIndex; // Safari 3.2.1
		return new Elements(Array.from(this.options).filter(function(option){
			return option.selected;
		}));
	},

	toQueryString: function(){
		var queryString = [];
		this.getElements('input, select, textarea').each(function(el){
			var type = el.type;
			if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return;

			var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){
				// IE
				return document.id(opt).get('value');
			}) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value');

			Array.from(value).each(function(val){
				if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val));
			});
		});
		return queryString.join('&');
	},

	destroy: function(){
		var children = clean(this).getElementsByTagName('*');
		Array.each(children, clean);
		Element.dispose(this);
		return null;
	},

	empty: function(){
		Array.from(this.childNodes).each(Element.dispose);
		return this;
	},

	dispose: function(){
		return (this.parentNode) ? this.parentNode.removeChild(this) : this;
	},

	match: function(expression){
		return !expression || Slick.match(this, expression);
	}

});

var cleanClone = function(node, element, keepid){
	if (!keepid) node.setAttributeNode(document.createAttribute('id'));
	if (node.clearAttributes){
		node.clearAttributes();
		node.mergeAttributes(element);
		node.removeAttribute('uid');
		if (node.options){
			var no = node.options, eo = element.options;
			for (var i = no.length; i--;) no[i].selected = eo[i].selected;
		}
	}

	var prop = formProps[element.tagName.toLowerCase()];
	if (prop && element[prop]) node[prop] = element[prop];
};

Element.implement('clone', function(contents, keepid){
	contents = contents !== false;
	var clone = this.cloneNode(contents), i;

	if (contents){
		var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*');
		for (i = ce.length; i--;) cleanClone(ce[i], te[i], keepid);
	}

	cleanClone(clone, this, keepid);

	if (Browser.ie){
		var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object');
		for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML;
	}
	return document.id(clone);
});

var contains = {contains: function(element){
	return Slick.contains(this, element);
}};

if (!document.contains) Document.implement(contains);
if (!document.createElement('div').contains) Element.implement(contains);

//<1.2compat>

Element.implement('hasChild', function(element){
	return this !== element && this.contains(element);
});

//</1.2compat>

[Element, Window, Document].invoke('implement', {

	addListener: function(type, fn){
		if (type == 'unload'){
			var old = fn, self = this;
			fn = function(){
				self.removeListener('unload', fn);
				old();
			};
		} else {
			collected[$uid(this)] = this;
		}
		if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]);
		else this.attachEvent('on' + type, fn);
		return this;
	},

	removeListener: function(type, fn){
		if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]);
		else this.detachEvent('on' + type, fn);
		return this;
	},

	retrieve: function(property, dflt){
		var storage = get($uid(this)), prop = storage[property];
		if (dflt != null && prop == null) prop = storage[property] = dflt;
		return prop != null ? prop : null;
	},

	store: function(property, value){
		var storage = get($uid(this));
		storage[property] = value;
		return this;
	},

	eliminate: function(property){
		var storage = get($uid(this));
		delete storage[property];
		return this;
	}

});

/*<ltIE9>*/
if (window.attachEvent && !window.addEventListener) window.addListener('unload', function(){
	Object.each(collected, clean);
	if (window.CollectGarbage) CollectGarbage();
});
/*</ltIE9>*/

})();

Element.Properties = {};

//<1.2compat>

Element.Properties = new Hash;

//</1.2compat>

Element.Properties.style = {

	set: function(style){
		this.style.cssText = style;
	},

	get: function(){
		return this.style.cssText;
	},

	erase: function(){
		this.style.cssText = '';
	}

};

Element.Properties.tag = {

	get: function(){
		return this.tagName.toLowerCase();
	}

};

/*<ltIE9>*/
(function(maxLength){
	if (maxLength != null) Element.Properties.maxlength = Element.Properties.maxLength = {
		get: function(){
			var maxlength = this.getAttribute('maxLength');
			return maxlength == maxLength ? null : maxlength;
		}
	};
})(document.createElement('input').getAttribute('maxLength'));
/*</ltIE9>*/

/*<!webkit>*/
Element.Properties.html = (function(){

	var tableTest = Function.attempt(function(){
		var table = document.createElement('table');
		table.innerHTML = '<tr><td></td></tr>';
	});

	var wrapper = document.createElement('div');

	var translations = {
		table: [1, '<table>', '</table>'],
		select: [1, '<select>', '</select>'],
		tbody: [2, '<table><tbody>', '</tbody></table>'],
		tr: [3, '<table><tbody><tr>', '</tr></tbody></table>']
	};
	translations.thead = translations.tfoot = translations.tbody;

	var html = {
		set: function(){
			var html = Array.flatten(arguments).join('');
			var wrap = (!tableTest && translations[this.get('tag')]);
			if (wrap){
				var first = wrapper;
				first.innerHTML = wrap[1] + html + wrap[2];
				for (var i = wrap[0]; i--;) first = first.firstChild;
				this.empty().adopt(first.childNodes);
			} else {
				this.innerHTML = html;
			}
		}
	};

	html.erase = html.set;

	return html;
})();
/*</!webkit>*/


/*
---

name: Element.Style

description: Contains methods for interacting with the styles of Elements in a fashionable way.

license: MIT-style license.

requires: Element

provides: Element.Style

...
*/

(function(){

var html = document.html;

Element.Properties.styles = {set: function(styles){
	this.setStyles(styles);
}};

var hasOpacity = (html.style.opacity != null);
var reAlpha = /alpha\(opacity=([\d.]+)\)/i;
var reAlpha2 = /alpha\(opacity:\s*([\d.]+)\s*\)/i;

var setOpacity = function(element, opacity){
	if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1;
	if (hasOpacity){
		element.style.opacity = opacity;
	} else {
		opacity = (opacity * 100).limit(0, 100).round();
		opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')';
		var filter = element.style.filter || element.getComputedStyle('filter') || '';
		element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : 
							   reAlpha2.test(filter) ? filter.replace(reAlpha2, opacity) :
							   filter + opacity;
	}
};

Element.Properties.opacity = {

	set: function(opacity){
		var visibility = this.style.visibility;
		if (opacity == 0 && visibility != 'hidden') this.style.visibility = 'hidden';
		else if (opacity != 0 && visibility != 'visible') this.style.visibility = 'visible';

		setOpacity(this, opacity);
	},

	get: (hasOpacity) ? function(){
		var opacity = this.style.opacity || this.getComputedStyle('opacity');
		return (opacity == '') ? 1 : opacity;
	} : function(){
		var opacity, filter = (this.style.filter || this.getComputedStyle('filter'));
		if (filter) opacity = filter.match(reAlpha);
		return (opacity == null || filter == null) ? 1 : (opacity[1] / 100);
	}

};

var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat';

Element.implement({

	getComputedStyle: function(property){
		if (this.currentStyle) return this.currentStyle[property.camelCase()];
		var defaultView = Element.getDocument(this).defaultView,
			computed = defaultView ? defaultView.getComputedStyle(this, null) : null;
		return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null;
	},

	setOpacity: function(value){
		setOpacity(this, value);
		return this;
	},

	getOpacity: function(){
		return this.get('opacity');
	},

	setStyle: function(property, value){
		switch (property){
			case 'opacity': return this.set('opacity', parseFloat(value));
			case 'float': property = floatName;
		}
		property = property.camelCase();
		if (typeOf(value) != 'string'){
			var map = (Element.Styles[property] || '@').split(' ');
			value = Array.from(value).map(function(val, i){
				if (!map[i]) return '';
				return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
			}).join(' ');
		} else if (value == String(Number(value))){
			value = Math.round(value);
		}
		this.style[property] = value;
		return this;
	},

	getStyle: function(property){
		switch (property){
			case 'opacity': return this.get('opacity');
			case 'float': property = floatName;
		}
		property = property.camelCase();
		var result = this.style[property];
		if (!result || property == 'zIndex'){
			result = [];
			for (var style in Element.ShortStyles){
				if (property != style) continue;
				for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
				return result.join(' ');
			}
			result = this.getComputedStyle(property);
		}
		if (result){
			result = String(result);
			var color = result.match(/rgba?\([\d\s,]+\)/);
			if (color) result = result.replace(color[0], color[0].rgbToHex());
		}
		if (Browser.opera || (Browser.ie && isNaN(parseFloat(result)))){
			if ((/^(height|width)$/).test(property)){
				var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
				values.each(function(value){
					size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
				}, this);
				return this['offset' + property.capitalize()] - size + 'px';
			}
			if (Browser.opera && String(result).indexOf('px') != -1) return result;
			if ((/^border(.+)Width|margin|padding/).test(property)) return '0px';
		}
		return result;
	},

	setStyles: function(styles){
		for (var style in styles) this.setStyle(style, styles[style]);
		return this;
	},

	getStyles: function(){
		var result = {};
		Array.flatten(arguments).each(function(key){
			result[key] = this.getStyle(key);
		}, this);
		return result;
	}

});

Element.Styles = {
	left: '@px', top: '@px', bottom: '@px', right: '@px',
	width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',
	backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
	fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
	margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
	borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
	zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'
};

//<1.2compat>

Element.Styles = new Hash(Element.Styles);

//</1.2compat>

Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};

['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
	var Short = Element.ShortStyles;
	var All = Element.Styles;
	['margin', 'padding'].each(function(style){
		var sd = style + direction;
		Short[style][sd] = All[sd] = '@px';
	});
	var bd = 'border' + direction;
	Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
	var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
	Short[bd] = {};
	Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
	Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
	Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
});

})();


/*
---

name: Element.Event

description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events.

license: MIT-style license.

requires: [Element, Event]

provides: Element.Event

...
*/

(function(){

Element.Properties.events = {set: function(events){
	this.addEvents(events);
}};

[Element, Window, Document].invoke('implement', {

	addEvent: function(type, fn){
		var events = this.retrieve('events', {});
		if (!events[type]) events[type] = {keys: [], values: []};
		if (events[type].keys.contains(fn)) return this;
		events[type].keys.push(fn);
		var realType = type,
			custom = Element.Events[type],
			condition = fn,
			self = this;
		if (custom){
			if (custom.onAdd) custom.onAdd.call(this, fn);
			if (custom.condition){
				condition = function(event){
					if (custom.condition.call(this, event)) return fn.call(this, event);
					return true;
				};
			}
			realType = custom.base || realType;
		}
		var defn = function(){
			return fn.call(self);
		};
		var nativeEvent = Element.NativeEvents[realType];
		if (nativeEvent){
			if (nativeEvent == 2){
				defn = function(event){
					event = new Event(event, self.getWindow());
					if (condition.call(self, event) === false) event.stop();
				};
			}
			this.addListener(realType, defn, arguments[2]);
		}
		events[type].values.push(defn);
		return this;
	},

	removeEvent: function(type, fn){
		var events = this.retrieve('events');
		if (!events || !events[type]) return this;
		var list = events[type];
		var index = list.keys.indexOf(fn);
		if (index == -1) return this;
		var value = list.values[index];
		delete list.keys[index];
		delete list.values[index];
		var custom = Element.Events[type];
		if (custom){
			if (custom.onRemove) custom.onRemove.call(this, fn);
			type = custom.base || type;
		}
		return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this;
	},

	addEvents: function(events){
		for (var event in events) this.addEvent(event, events[event]);
		return this;
	},

	removeEvents: function(events){
		var type;
		if (typeOf(events) == 'object'){
			for (type in events) this.removeEvent(type, events[type]);
			return this;
		}
		var attached = this.retrieve('events');
		if (!attached) return this;
		if (!events){
			for (type in attached) this.removeEvents(type);
			this.eliminate('events');
		} else if (attached[events]){
			attached[events].keys.each(function(fn){
				this.removeEvent(events, fn);
			}, this);
			delete attached[events];
		}
		return this;
	},

	fireEvent: function(type, args, delay){
		var events = this.retrieve('events');
		if (!events || !events[type]) return this;
		args = Array.from(args);

		events[type].keys.each(function(fn){
			if (delay) fn.delay(delay, this, args);
			else fn.apply(this, args);
		}, this);
		return this;
	},

	cloneEvents: function(from, type){
		from = document.id(from);
		var events = from.retrieve('events');
		if (!events) return this;
		if (!type){
			for (var eventType in events) this.cloneEvents(from, eventType);
		} else if (events[type]){
			events[type].keys.each(function(fn){
				this.addEvent(type, fn);
			}, this);
		}
		return this;
	}

});

Element.NativeEvents = {
	click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
	mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
	mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
	keydown: 2, keypress: 2, keyup: 2, //keyboard
	orientationchange: 2, // mobile
	touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch
	gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture
	focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements
	load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
	error: 1, abort: 1, scroll: 1 //misc
};

var check = function(event){
	var related = event.relatedTarget;
	if (related == null) return true;
	if (!related) return false;
	return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related));
};

Element.Events = {

	mouseenter: {
		base: 'mouseover',
		condition: check
	},

	mouseleave: {
		base: 'mouseout',
		condition: check
	},

	mousewheel: {
		base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel'
	}

};

//<1.2compat>

Element.Events = new Hash(Element.Events);

//</1.2compat>

})();


/*
---

name: Element.Dimensions

description: Contains methods to work with size, scroll, or positioning of Elements and the window object.

license: MIT-style license.

credits:
  - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html).
  - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html).

requires: [Element, Element.Style]

provides: [Element.Dimensions]

...
*/

(function(){

var element = document.createElement('div'),
	child = document.createElement('div');
element.style.height = '0';
element.appendChild(child);
var brokenOffsetParent = (child.offsetParent === element);
element = child = null;

var isOffset = function(el){
	return styleString(el, 'position') != 'static' || isBody(el);
};

var isOffsetStatic = function(el){
	return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName);
};

Element.implement({

	scrollTo: function(x, y){
		if (isBody(this)){
			this.getWindow().scrollTo(x, y);
		} else {
			this.scrollLeft = x;
			this.scrollTop = y;
		}
		return this;
	},

	getSize: function(){
		if (isBody(this)) return this.getWindow().getSize();
		return {x: this.offsetWidth, y: this.offsetHeight};
	},

	getScrollSize: function(){
		if (isBody(this)) return this.getWindow().getScrollSize();
		return {x: this.scrollWidth, y: this.scrollHeight};
	},

	getScroll: function(){
		if (isBody(this)) return this.getWindow().getScroll();
		return {x: this.scrollLeft, y: this.scrollTop};
	},

	getScrolls: function(){
		var element = this.parentNode, position = {x: 0, y: 0};
		while (element && !isBody(element)){
			position.x += element.scrollLeft;
			position.y += element.scrollTop;
			element = element.parentNode;
		}
		return position;
	},

	getOffsetParent: brokenOffsetParent ? function(){
		var element = this;
		if (isBody(element) || styleString(element, 'position') == 'fixed') return null;

		var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset;
		while ((element = element.parentNode)){
			if (isOffsetCheck(element)) return element;
		}
		return null;
	} : function(){
		var element = this;
		if (isBody(element) || styleString(element, 'position') == 'fixed') return null;

		try {
			return element.offsetParent;
		} catch(e) {}
		return null;
	},

	getOffsets: function(){
		if (this.getBoundingClientRect && !Browser.Platform.ios){
			var bound = this.getBoundingClientRect(),
				html = document.id(this.getDocument().documentElement),
				htmlScroll = html.getScroll(),
				elemScrolls = this.getScrolls(),
				isFixed = (styleString(this, 'position') == 'fixed');

			return {
				x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft,
				y: bound.top.toInt()  + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop
			};
		}

		var element = this, position = {x: 0, y: 0};
		if (isBody(this)) return position;

		while (element && !isBody(element)){
			position.x += element.offsetLeft;
			position.y += element.offsetTop;

			if (Browser.firefox){
				if (!borderBox(element)){
					position.x += leftBorder(element);
					position.y += topBorder(element);
				}
				var parent = element.parentNode;
				if (parent && styleString(parent, 'overflow') != 'visible'){
					position.x += leftBorder(parent);
					position.y += topBorder(parent);
				}
			} else if (element != this && Browser.safari){
				position.x += leftBorder(element);
				position.y += topBorder(element);
			}

			element = element.offsetParent;
		}
		if (Browser.firefox && !borderBox(this)){
			position.x -= leftBorder(this);
			position.y -= topBorder(this);
		}
		return position;
	},

	getPosition: function(relative){
		if (isBody(this)) return {x: 0, y: 0};
		var offset = this.getOffsets(),
			scroll = this.getScrolls();
		var position = {
			x: offset.x - scroll.x,
			y: offset.y - scroll.y
		};
		
		if (relative && (relative = document.id(relative))){
			var relativePosition = relative.getPosition();
			return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)};
		}
		return position;
	},

	getCoordinates: function(element){
		if (isBody(this)) return this.getWindow().getCoordinates();
		var position = this.getPosition(element),
			size = this.getSize();
		var obj = {
			left: position.x,
			top: position.y,
			width: size.x,
			height: size.y
		};
		obj.right = obj.left + obj.width;
		obj.bottom = obj.top + obj.height;
		return obj;
	},

	computePosition: function(obj){
		return {
			left: obj.x - styleNumber(this, 'margin-left'),
			top: obj.y - styleNumber(this, 'margin-top')
		};
	},

	setPosition: function(obj) {
		return this.setStyles(this.computePosition(obj));
	}

});


[Document, Window].invoke('implement', {

	getSize: function(){
		var doc = getCompatElement(this);
		return {x: doc.clientWidth, y: doc.clientHeight};
	},

	getScroll: function(){
		var win = this.getWindow(), doc = getCompatElement(this);
		return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
	},

	getScrollSize: function(){
		var doc = getCompatElement(this),
			min = this.getSize(),
			body = this.getDocument().body;

		return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)};
	},

	getPosition: function(){
		return {x: 0, y: 0};
	},

	getCoordinates: function(){
		var size = this.getSize();
		return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
	}

});

// private methods

var styleString = Element.getComputedStyle;

function styleNumber(element, style){
	return styleString(element, style).toInt() || 0;
}

function borderBox(element){
	return styleString(element, '-moz-box-sizing') == 'border-box';
}

function topBorder(element){
	return styleNumber(element, 'border-top-width');
}

function leftBorder(element){
	return styleNumber(element, 'border-left-width');
}

function isBody(element){
	return (/^(?:body|html)$/i).test(element.tagName);
}

function getCompatElement(element){
	var doc = element.getDocument();
	return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
}

})();

//aliases
Element.alias({position: 'setPosition'}); //compatability

[Window, Document, Element].invoke('implement', {

	getHeight: function(){
		return this.getSize().y;
	},

	getWidth: function(){
		return this.getSize().x;
	},

	getScrollTop: function(){
		return this.getScroll().y;
	},

	getScrollLeft: function(){
		return this.getScroll().x;
	},

	getScrollHeight: function(){
		return this.getScrollSize().y;
	},

	getScrollWidth: function(){
		return this.getScrollSize().x;
	},

	getTop: function(){
		return this.getPosition().y;
	},

	getLeft: function(){
		return this.getPosition().x;
	}

});


/*
---

name: Fx

description: Contains the basic animation logic to be extended by all other Fx Classes.

license: MIT-style license.

requires: [Chain, Events, Options]

provides: Fx

...
*/

(function(){

var Fx = this.Fx = new Class({

	Implements: [Chain, Events, Options],

	options: {
		/*
		onStart: nil,
		onCancel: nil,
		onComplete: nil,
		*/
		fps: 60,
		unit: false,
		duration: 500,
		frames: null,
		frameSkip: true,
		link: 'ignore'
	},

	initialize: function(options){
		this.subject = this.subject || this;
		this.setOptions(options);
	},

	getTransition: function(){
		return function(p){
			return -(Math.cos(Math.PI * p) - 1) / 2;
		};
	},

	step: function(now){
		if (this.options.frameSkip){
			var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval;
			this.time = now;
			this.frame += frames;
		} else {
			this.frame++;
		}
		
		if (this.frame < this.frames){
			var delta = this.transition(this.frame / this.frames);
			this.set(this.compute(this.from, this.to, delta));
		} else {
			this.frame = this.frames;
			this.set(this.compute(this.from, this.to, 1));
			this.stop();
		}
	},

	set: function(now){
		return now;
	},

	compute: function(from, to, delta){
		return Fx.compute(from, to, delta);
	},

	check: function(){
		if (!this.isRunning()) return true;
		switch (this.options.link){
			case 'cancel': this.cancel(); return true;
			case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
		}
		return false;
	},

	start: function(from, to){
		if (!this.check(from, to)) return this;
		this.from = from;
		this.to = to;
		this.frame = (this.options.frameSkip) ? 0 : -1;
		this.time = null;
		this.transition = this.getTransition();
		var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration;
		this.duration = Fx.Durations[duration] || duration.toInt();
		this.frameInterval = 1000 / fps;
		this.frames = frames || Math.round(this.duration / this.frameInterval);
		this.fireEvent('start', this.subject);
		pushInstance.call(this, fps);
		return this;
	},
	
	stop: function(){
		if (this.isRunning()){
			this.time = null;
			pullInstance.call(this, this.options.fps);
			if (this.frames == this.frame){
				this.fireEvent('complete', this.subject);
				if (!this.callChain()) this.fireEvent('chainComplete', this.subject);
			} else {
				this.fireEvent('stop', this.subject);
			}
		}
		return this;
	},
	
	cancel: function(){
		if (this.isRunning()){
			this.time = null;
			pullInstance.call(this, this.options.fps);
			this.frame = this.frames;
			this.fireEvent('cancel', this.subject).clearChain();
		}
		return this;
	},
	
	pause: function(){
		if (this.isRunning()){
			this.time = null;
			pullInstance.call(this, this.options.fps);
		}
		return this;
	},
	
	resume: function(){
		if ((this.frame < this.frames) && !this.isRunning()) pushInstance.call(this, this.options.fps);
		return this;
	},
	
	isRunning: function(){
		var list = instances[this.options.fps];
		return list && list.contains(this);
	}

});

Fx.compute = function(from, to, delta){
	return (to - from) * delta + from;
};

Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};

// global timers

var instances = {}, timers = {};

var loop = function(){
	var now = Date.now();
	for (var i = this.length; i--;){
		var instance = this[i];
		if (instance) instance.step(now);
	}
};

var pushInstance = function(fps){
	var list = instances[fps] || (instances[fps] = []);
	list.push(this);
	if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list);
};

var pullInstance = function(fps){
	var list = instances[fps];
	if (list){
		list.erase(this);
		if (!list.length && timers[fps]){
			delete instances[fps];
			timers[fps] = clearInterval(timers[fps]);
		}
	}
};

})();


/*
---

name: Fx.CSS

description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.

license: MIT-style license.

requires: [Fx, Element.Style]

provides: Fx.CSS

...
*/

Fx.CSS = new Class({

	Extends: Fx,

	//prepares the base from/to object

	prepare: function(element, property, values){
		values = Array.from(values);
		if (values[1] == null){
			values[1] = values[0];
			values[0] = element.getStyle(property);
		}
		var parsed = values.map(this.parse);
		return {from: parsed[0], to: parsed[1]};
	},

	//parses a value into an array

	parse: function(value){
		value = Function.from(value)();
		value = (typeof value == 'string') ? value.split(' ') : Array.from(value);
		return value.map(function(val){
			val = String(val);
			var found = false;
			Object.each(Fx.CSS.Parsers, function(parser, key){
				if (found) return;
				var parsed = parser.parse(val);
				if (parsed || parsed === 0) found = {value: parsed, parser: parser};
			});
			found = found || {value: val, parser: Fx.CSS.Parsers.String};
			return found;
		});
	},

	//computes by a from and to prepared objects, using their parsers.

	compute: function(from, to, delta){
		var computed = [];
		(Math.min(from.length, to.length)).times(function(i){
			computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
		});
		computed.$family = Function.from('fx:css:value');
		return computed;
	},

	//serves the value as settable

	serve: function(value, unit){
		if (typeOf(value) != 'fx:css:value') value = this.parse(value);
		var returned = [];
		value.each(function(bit){
			returned = returned.concat(bit.parser.serve(bit.value, unit));
		});
		return returned;
	},

	//renders the change to an element

	render: function(element, property, value, unit){
		element.setStyle(property, this.serve(value, unit));
	},

	//searches inside the page css to find the values for a selector

	search: function(selector){
		if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
		var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$');
		Array.each(document.styleSheets, function(sheet, j){
			var href = sheet.href;
			if (href && href.contains('://') && !href.contains(document.domain)) return;
			var rules = sheet.rules || sheet.cssRules;
			Array.each(rules, function(rule, i){
				if (!rule.style) return;
				var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){
					return m.toLowerCase();
				}) : null;
				if (!selectorText || !selectorTest.test(selectorText)) return;
				Object.each(Element.Styles, function(value, style){
					if (!rule.style[style] || Element.ShortStyles[style]) return;
					value = String(rule.style[style]);
					to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value;
				});
			});
		});
		return Fx.CSS.Cache[selector] = to;
	}

});

Fx.CSS.Cache = {};

Fx.CSS.Parsers = {

	Color: {
		parse: function(value){
			if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
			return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
		},
		compute: function(from, to, delta){
			return from.map(function(value, i){
				return Math.round(Fx.compute(from[i], to[i], delta));
			});
		},
		serve: function(value){
			return value.map(Number);
		}
	},

	Number: {
		parse: parseFloat,
		compute: Fx.compute,
		serve: function(value, unit){
			return (unit) ? value + unit : value;
		}
	},

	String: {
		parse: Function.from(false),
		compute: function(zero, one){
			return one;
		},
		serve: function(zero){
			return zero;
		}
	}

};

//<1.2compat>

Fx.CSS.Parsers = new Hash(Fx.CSS.Parsers);

//</1.2compat>


/*
---

name: Fx.Tween

description: Formerly Fx.Style, effect to transition any CSS property for an element.

license: MIT-style license.

requires: Fx.CSS

provides: [Fx.Tween, Element.fade, Element.highlight]

...
*/

Fx.Tween = new Class({

	Extends: Fx.CSS,

	initialize: function(element, options){
		this.element = this.subject = document.id(element);
		this.parent(options);
	},

	set: function(property, now){
		if (arguments.length == 1){
			now = property;
			property = this.property || this.options.property;
		}
		this.render(this.element, property, now, this.options.unit);
		return this;
	},

	start: function(property, from, to){
		if (!this.check(property, from, to)) return this;
		var args = Array.flatten(arguments);
		this.property = this.options.property || args.shift();
		var parsed = this.prepare(this.element, this.property, args);
		return this.parent(parsed.from, parsed.to);
	}

});

Element.Properties.tween = {

	set: function(options){
		this.get('tween').cancel().setOptions(options);
		return this;
	},

	get: function(){
		var tween = this.retrieve('tween');
		if (!tween){
			tween = new Fx.Tween(this, {link: 'cancel'});
			this.store('tween', tween);
		}
		return tween;
	}

};

Element.implement({

	tween: function(property, from, to){
		this.get('tween').start(arguments);
		return this;
	},

	fade: function(how){
		var fade = this.get('tween'), o = 'opacity', toggle;
		how = [how, 'toggle'].pick();
		switch (how){
			case 'in': fade.start(o, 1); break;
			case 'out': fade.start(o, 0); break;
			case 'show': fade.set(o, 1); break;
			case 'hide': fade.set(o, 0); break;
			case 'toggle':
				var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
				fade.start(o, (flag) ? 0 : 1);
				this.store('fade:flag', !flag);
				toggle = true;
			break;
			default: fade.start(o, arguments);
		}
		if (!toggle) this.eliminate('fade:flag');
		return this;
	},

	highlight: function(start, end){
		if (!end){
			end = this.retrieve('highlight:original', this.getStyle('background-color'));
			end = (end == 'transparent') ? '#fff' : end;
		}
		var tween = this.get('tween');
		tween.start('background-color', start || '#ffff88', end).chain(function(){
			this.setStyle('background-color', this.retrieve('highlight:original'));
			tween.callChain();
		}.bind(this));
		return this;
	}

});


/*
---

name: Fx.Morph

description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules.

license: MIT-style license.

requires: Fx.CSS

provides: Fx.Morph

...
*/

Fx.Morph = new Class({

	Extends: Fx.CSS,

	initialize: function(element, options){
		this.element = this.subject = document.id(element);
		this.parent(options);
	},

	set: function(now){
		if (typeof now == 'string') now = this.search(now);
		for (var p in now) this.render(this.element, p, now[p], this.options.unit);
		return this;
	},

	compute: function(from, to, delta){
		var now = {};
		for (var p in from) now[p] = this.parent(from[p], to[p], delta);
		return now;
	},

	start: function(properties){
		if (!this.check(properties)) return this;
		if (typeof properties == 'string') properties = this.search(properties);
		var from = {}, to = {};
		for (var p in properties){
			var parsed = this.prepare(this.element, p, properties[p]);
			from[p] = parsed.from;
			to[p] = parsed.to;
		}
		return this.parent(from, to);
	}

});

Element.Properties.morph = {

	set: function(options){
		this.get('morph').cancel().setOptions(options);
		return this;
	},

	get: function(){
		var morph = this.retrieve('morph');
		if (!morph){
			morph = new Fx.Morph(this, {link: 'cancel'});
			this.store('morph', morph);
		}
		return morph;
	}

};

Element.implement({

	morph: function(props){
		this.get('morph').start(props);
		return this;
	}

});


/*
---

name: Fx.Transitions

description: Contains a set of advanced transitions to be used with any of the Fx Classes.

license: MIT-style license.

credits:
  - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.

requires: Fx

provides: Fx.Transitions

...
*/

Fx.implement({

	getTransition: function(){
		var trans = this.options.transition || Fx.Transitions.Sine.easeInOut;
		if (typeof trans == 'string'){
			var data = trans.split(':');
			trans = Fx.Transitions;
			trans = trans[data[0]] || trans[data[0].capitalize()];
			if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')];
		}
		return trans;
	}

});

Fx.Transition = function(transition, params){
	params = Array.from(params);
	var easeIn = function(pos){
		return transition(pos, params);
	};
	return Object.append(easeIn, {
		easeIn: easeIn,
		easeOut: function(pos){
			return 1 - transition(1 - pos, params);
		},
		easeInOut: function(pos){
			return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2;
		}
	});
};

Fx.Transitions = {

	linear: function(zero){
		return zero;
	}

};

//<1.2compat>

Fx.Transitions = new Hash(Fx.Transitions);

//</1.2compat>

Fx.Transitions.extend = function(transitions){
	for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
};

Fx.Transitions.extend({

	Pow: function(p, x){
		return Math.pow(p, x && x[0] || 6);
	},

	Expo: function(p){
		return Math.pow(2, 8 * (p - 1));
	},

	Circ: function(p){
		return 1 - Math.sin(Math.acos(p));
	},

	Sine: function(p){
		return 1 - Math.cos(p * Math.PI / 2);
	},

	Back: function(p, x){
		x = x && x[0] || 1.618;
		return Math.pow(p, 2) * ((x + 1) * p - x);
	},

	Bounce: function(p){
		var value;
		for (var a = 0, b = 1; 1; a += b, b /= 2){
			if (p >= (7 - 4 * a) / 11){
				value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
				break;
			}
		}
		return value;
	},

	Elastic: function(p, x){
		return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3);
	}

});

['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
	Fx.Transitions[transition] = new Fx.Transition(function(p){
		return Math.pow(p, i + 2);
	});
});


/*
---

name: Request

description: Powerful all purpose Request Class. Uses XMLHTTPRequest.

license: MIT-style license.

requires: [Object, Element, Chain, Events, Options, Browser]

provides: Request

...
*/

(function(){

var empty = function(){},
	progressSupport = ('onprogress' in new Browser.Request);

var Request = this.Request = new Class({

	Implements: [Chain, Events, Options],

	options: {/*
		onRequest: function(){},
		onLoadstart: function(event, xhr){},
		onProgress: function(event, xhr){},
		onComplete: function(){},
		onCancel: function(){},
		onSuccess: function(responseText, responseXML){},
		onFailure: function(xhr){},
		onException: function(headerName, value){},
		onTimeout: function(){},
		user: '',
		password: '',*/
		url: '',
		data: '',
		headers: {
			'X-Requested-With': 'XMLHttpRequest',
			'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
		},
		async: true,
		format: false,
		method: 'post',
		link: 'ignore',
		isSuccess: null,
		emulation: true,
		urlEncoded: true,
		encoding: 'utf-8',
		evalScripts: false,
		evalResponse: false,
		timeout: 0,
		noCache: false
	},

	initialize: function(options){
		this.xhr = new Browser.Request();
		this.setOptions(options);
		this.headers = this.options.headers;
	},

	onStateChange: function(){
		var xhr = this.xhr;
		if (xhr.readyState != 4 || !this.running) return;
		this.running = false;
		this.status = 0;
		Function.attempt(function(){
			var status = xhr.status;
			this.status = (status == 1223) ? 204 : status;
		}.bind(this));
		xhr.onreadystatechange = empty;
		if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
		clearTimeout(this.timer);
		
		this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML};
		if (this.options.isSuccess.call(this, this.status))
			this.success(this.response.text, this.response.xml);
		else
			this.failure();
	},

	isSuccess: function(){
		var status = this.status;
		return (status >= 200 && status < 300);
	},

	isRunning: function(){
		return !!this.running;
	},

	processScripts: function(text){
		if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text);
		return text.stripScripts(this.options.evalScripts);
	},

	success: function(text, xml){
		this.onSuccess(this.processScripts(text), xml);
	},

	onSuccess: function(){
		this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain();
	},

	failure: function(){
		this.onFailure();
	},

	onFailure: function(){
		this.fireEvent('complete').fireEvent('failure', this.xhr);
	},
	
	loadstart: function(event){
		this.fireEvent('loadstart', [event, this.xhr]);
	},
	
	progress: function(event){
		this.fireEvent('progress', [event, this.xhr]);
	},
	
	timeout: function(){
		this.fireEvent('timeout', this.xhr);
	},

	setHeader: function(name, value){
		this.headers[name] = value;
		return this;
	},

	getHeader: function(name){
		return Function.attempt(function(){
			return this.xhr.getResponseHeader(name);
		}.bind(this));
	},

	check: function(){
		if (!this.running) return true;
		switch (this.options.link){
			case 'cancel': this.cancel(); return true;
			case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
		}
		return false;
	},
	
	send: function(options){
		if (!this.check(options)) return this;

		this.options.isSuccess = this.options.isSuccess || this.isSuccess;
		this.running = true;

		var type = typeOf(options);
		if (type == 'string' || type == 'element') options = {data: options};

		var old = this.options;
		options = Object.append({data: old.data, url: old.url, method: old.method}, options);
		var data = options.data, url = String(options.url), method = options.method.toLowerCase();

		switch (typeOf(data)){
			case 'element': data = document.id(data).toQueryString(); break;
			case 'object': case 'hash': data = Object.toQueryString(data);
		}

		if (this.options.format){
			var format = 'format=' + this.options.format;
			data = (data) ? format + '&' + data : format;
		}

		if (this.options.emulation && !['get', 'post'].contains(method)){
			var _method = '_method=' + method;
			data = (data) ? _method + '&' + data : _method;
			method = 'post';
		}

		if (this.options.urlEncoded && ['post', 'put'].contains(method)){
			var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
			this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding;
		}

		if (!url) url = document.location.pathname;
		
		var trimPosition = url.lastIndexOf('/');
		if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition);

		if (this.options.noCache)
			url += (url.contains('?') ? '&' : '?') + String.uniqueID();

		if (data && method == 'get'){
			url += (url.contains('?') ? '&' : '?') + data;
			data = null;
		}

		var xhr = this.xhr;
		if (progressSupport){
			xhr.onloadstart = this.loadstart.bind(this);
			xhr.onprogress = this.progress.bind(this);
		}

		xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password);
		if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true;
		
		xhr.onreadystatechange = this.onStateChange.bind(this);

		Object.each(this.headers, function(value, key){
			try {
				xhr.setRequestHeader(key, value);
			} catch (e){
				this.fireEvent('exception', [key, value]);
			}
		}, this);

		this.fireEvent('request');
		xhr.send(data);
		if (!this.options.async) this.onStateChange();
		if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this);
		return this;
	},

	cancel: function(){
		if (!this.running) return this;
		this.running = false;
		var xhr = this.xhr;
		xhr.abort();
		clearTimeout(this.timer);
		xhr.onreadystatechange = empty;
		if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
		this.xhr = new Browser.Request();
		this.fireEvent('cancel');
		return this;
	}

});

var methods = {};
['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){
	methods[method] = function(data){
		var object = {
			method: method
		};
		if (data != null) object.data = data;
		return this.send(object);
	};
});

Request.implement(methods);

Element.Properties.send = {

	set: function(options){
		var send = this.get('send').cancel();
		send.setOptions(options);
		return this;
	},

	get: function(){
		var send = this.retrieve('send');
		if (!send){
			send = new Request({
				data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
			});
			this.store('send', send);
		}
		return send;
	}

};

Element.implement({

	send: function(url){
		var sender = this.get('send');
		sender.send({data: this, url: url || sender.options.url});
		return this;
	}

});

})();

/*
---

name: Request.HTML

description: Extends the basic Request Class with additional methods for interacting with HTML responses.

license: MIT-style license.

requires: [Element, Request]

provides: Request.HTML

...
*/

Request.HTML = new Class({

	Extends: Request,

	options: {
		update: false,
		append: false,
		evalScripts: true,
		filter: false,
		headers: {
			Accept: 'text/html, application/xml, text/xml, */*'
		}
	},

	success: function(text){
		var options = this.options, response = this.response;

		response.html = text.stripScripts(function(script){
			response.javascript = script;
		});

		var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
		if (match) response.html = match[1];
		var temp = new Element('div').set('html', response.html);

		response.tree = temp.childNodes;
		response.elements = temp.getElements('*');

		if (options.filter) response.tree = response.elements.filter(options.filter);
		if (options.update) document.id(options.update).empty().set('html', response.html);
		else if (options.append) document.id(options.append).adopt(temp.getChildren());
		if (options.evalScripts) Browser.exec(response.javascript);

		this.onSuccess(response.tree, response.elements, response.html, response.javascript);
	}

});

Element.Properties.load = {

	set: function(options){
		var load = this.get('load').cancel();
		load.setOptions(options);
		return this;
	},

	get: function(){
		var load = this.retrieve('load');
		if (!load){
			load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'});
			this.store('load', load);
		}
		return load;
	}

};

Element.implement({

	load: function(){
		this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString}));
		return this;
	}

});


/*
---

name: JSON

description: JSON encoder and decoder.

license: MIT-style license.

See Also: <http://www.json.org/>

requires: [Array, String, Number, Function]

provides: JSON

...
*/

if (typeof JSON == 'undefined') JSON = {};

//</1.2compat>

(function(){

var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'};

var escape = function(chr){
	return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4);
};

JSON.validate = function(string){
	string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
					replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
					replace(/(?:^|:|,)(?:\s*\[)+/g, '');

	return (/^[\],:{}\s]*$/).test(string);
};

JSON.encode = function(obj){
    try {
        if (JSON.stringify) return JSON.stringify(obj);
    } catch(e) {}

    if (obj && obj.toJSON) obj = obj.toJSON();

	switch (typeOf(obj)){
		case 'string':
			return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"';
		case 'array':
			return '[' + obj.map(JSON.encode).clean() + ']';
		case 'object': case 'hash':
			var string = [];
			Object.each(obj, function(value, key){
				var json = JSON.encode(value);
				if (json) string.push(JSON.encode(key) + ':' + json);
			});
			return '{' + string + '}';
		case 'number': case 'boolean': return '' + obj;
		case 'null': return 'null';
	}

	return null;
};

JSON.decode = function(string, secure){
    try {
        if (JSON.parse) return JSON.parse(string);
    } catch(e) {}
	if (!string || typeOf(string) != 'string') return null;

	if (secure || JSON.secure){
		if (JSON.parse) return JSON.parse(string);
		if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.');
	}

	return eval('(' + string + ')');
};

})();


/*
---

name: Request.JSON

description: Extends the basic Request Class with additional methods for sending and receiving JSON data.

license: MIT-style license.

requires: [Request, JSON]

provides: Request.JSON

...
*/

Request.JSON = new Class({

	Extends: Request,

	options: {
		/*onError: function(text, error){},*/
		secure: true
	},

	initialize: function(options){
		this.parent(options);
		Object.append(this.headers, {
			'Accept': 'application/json',
			'X-Request': 'JSON'
		});
	},

	success: function(text){
		var json;
		try {
			json = this.response.json = JSON.decode(text, this.options.secure);
		} catch (error){
			this.fireEvent('error', [text, error]);
			return;
		}
		if (json == null) this.onFailure();
		else this.onSuccess(json, text);
	}

});


/*
---

name: Cookie

description: Class for creating, reading, and deleting browser Cookies.

license: MIT-style license.

credits:
  - Based on the functions by Peter-Paul Koch (http://quirksmode.org).

requires: [Options, Browser]

provides: Cookie

...
*/

var Cookie = new Class({

	Implements: Options,

	options: {
		path: '/',
		domain: false,
		duration: false,
		secure: false,
		document: document,
		encode: true
	},

	initialize: function(key, options){
		this.key = key;
		this.setOptions(options);
	},

	write: function(value){
		if (this.options.encode) value = encodeURIComponent(value);
		if (this.options.domain) value += '; domain=' + this.options.domain;
		if (this.options.path) value += '; path=' + this.options.path;
		if (this.options.duration){
			var date = new Date();
			date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
			value += '; expires=' + date.toGMTString();
		}
		if (this.options.secure) value += '; secure';
		this.options.document.cookie = this.key + '=' + value;
		return this;
	},

	read: function(){
		var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
		return (value) ? decodeURIComponent(value[1]) : null;
	},

	dispose: function(){
		new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write('');
		return this;
	}

});

Cookie.write = function(key, value, options){
	return new Cookie(key, options).write(value);
};

Cookie.read = function(key){
	return new Cookie(key).read();
};

Cookie.dispose = function(key, options){
	return new Cookie(key, options).dispose();
};


/*
---

name: DOMReady

description: Contains the custom event domready.

license: MIT-style license.

requires: [Browser, Element, Element.Event]

provides: [DOMReady, DomReady]

...
*/

(function(window, document){

var ready,
	loaded,
	checks = [],
	shouldPoll,
	timer,
	testElement = document.createElement('div');

var domready = function(){
	clearTimeout(timer);
	if (ready) return;
	Browser.loaded = ready = true;
	document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check);
	
	document.fireEvent('domready');
	window.fireEvent('domready');
};

var check = function(){
	for (var i = checks.length; i--;) if (checks[i]()){
		domready();
		return true;
	}
	return false;
};

var poll = function(){
	clearTimeout(timer);
	if (!check()) timer = setTimeout(poll, 10);
};

document.addListener('DOMContentLoaded', domready);

/*<ltIE8>*/
// doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/
// testElement.doScroll() throws when the DOM is not ready, only in the top window
var doScrollWorks = function(){
	try {
		testElement.doScroll();
		return true;
	} catch (e){}
	return false;
}
// If doScroll works already, it can't be used to determine domready
//   e.g. in an iframe
if (testElement.doScroll && !doScrollWorks()){
	checks.push(doScrollWorks);
	shouldPoll = true;
}
/*</ltIE8>*/

if (document.readyState) checks.push(function(){
	var state = document.readyState;
	return (state == 'loaded' || state == 'complete');
});

if ('onreadystatechange' in document) document.addListener('readystatechange', check);
else shouldPoll = true;

if (shouldPoll) poll();

Element.Events.domready = {
	onAdd: function(fn){
		if (ready) fn.call(this);
	}
};

// Make sure that domready fires before load
Element.Events.load = {
	base: 'load',
	onAdd: function(fn){
		if (loaded && this == window) fn.call(this);
	},
	condition: function(){
		if (this == window){
			domready();
			delete Element.Events.load;
		}
		return true;
	}
};

// This is based on the custom load event
window.addEvent('load', function(){
	loaded = true;
});

})(window, document);


/*
---

name: Swiff

description: Wrapper for embedding SWF movies. Supports External Interface Communication.

license: MIT-style license.

credits:
  - Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject.

requires: [Options, Object, Element]

provides: Swiff

...
*/

(function(){

var Swiff = this.Swiff = new Class({

	Implements: Options,

	options: {
		id: null,
		height: 1,
		width: 1,
		container: null,
		properties: {},
		params: {
			quality: 'high',
			allowScriptAccess: 'always',
			wMode: 'window',
			swLiveConnect: true
		},
		callBacks: {},
		vars: {}
	},

	toElement: function(){
		return this.object;
	},

	initialize: function(path, options){
		this.instance = 'Swiff_' + String.uniqueID();

		this.setOptions(options);
		options = this.options;
		var id = this.id = options.id || this.instance;
		var container = document.id(options.container);

		Swiff.CallBacks[this.instance] = {};

		var params = options.params, vars = options.vars, callBacks = options.callBacks;
		var properties = Object.append({height: options.height, width: options.width}, options.properties);

		var self = this;

		for (var callBack in callBacks){
			Swiff.CallBacks[this.instance][callBack] = (function(option){
				return function(){
					return option.apply(self.object, arguments);
				};
			})(callBacks[callBack]);
			vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack;
		}

		params.flashVars = Object.toQueryString(vars);
		if (Browser.ie){
			properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
			params.movie = path;
		} else {
			properties.type = 'application/x-shockwave-flash';
		}
		properties.data = path;

		var build = '<object id="' + id + '"';
		for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
		build += '>';
		for (var param in params){
			if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />';
		}
		build += '</object>';
		this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild;
	},

	replaces: function(element){
		element = document.id(element, true);
		element.parentNode.replaceChild(this.toElement(), element);
		return this;
	},

	inject: function(element){
		document.id(element, true).appendChild(this.toElement());
		return this;
	},

	remote: function(){
		return Swiff.remote.apply(Swiff, [this.toElement()].append(arguments));
	}

});

Swiff.CallBacks = {};

Swiff.remote = function(obj, fn){
	var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
	return eval(rs);
};

})();

MooTools.More = {
		'version': '1.3.2.1',
		'build': 'e586bcd2496e9b22acfde32e12f84d49ce09e59d'
	};


	/*
	---

	script: Fx.Scroll.js

	name: Fx.Scroll

	description: Effect to smoothly scroll any element, including the window.

	license: MIT-style license

	authors:
	  - Valerio Proietti

	requires:
	  - Core/Fx
	  - Core/Element.Event
	  - Core/Element.Dimensions
	  - /MooTools.More

	provides: [Fx.Scroll]

	...
	*/

	(function(){

	Fx.Scroll = new Class({

		Extends: Fx,

		options: {
			offset: {x: 0, y: 0},
			wheelStops: true
		},

		initialize: function(element, options){
			this.element = this.subject = document.id(element);
			this.parent(options);

			if (typeOf(this.element) != 'element') this.element = document.id(this.element.getDocument().body);

			if (this.options.wheelStops){
				var stopper = this.element,
					cancel = this.cancel.pass(false, this);
				this.addEvent('start', function(){
					stopper.addEvent('mousewheel', cancel);
				}, true);
				this.addEvent('complete', function(){
					stopper.removeEvent('mousewheel', cancel);
				}, true);
			}
		},

		set: function(){
			var now = Array.flatten(arguments);
			if (Browser.firefox) now = [Math.round(now[0]), Math.round(now[1])]; // not needed anymore in newer firefox versions
			this.element.scrollTo(now[0], now[1]);
			return this;
		},

		compute: function(from, to, delta){
			return [0, 1].map(function(i){
				return Fx.compute(from[i], to[i], delta);
			});
		},

		start: function(x, y){
			if (!this.check(x, y)) return this;
			var scroll = this.element.getScroll();
			return this.parent([scroll.x, scroll.y], [x, y]);
		},

		calculateScroll: function(x, y){
			var element = this.element,
				scrollSize = element.getScrollSize(),
				scroll = element.getScroll(),
				size = element.getSize(),
				offset = this.options.offset,
				values = {x: x, y: y};

			for (var z in values){
				if (!values[z] && values[z] !== 0) values[z] = scroll[z];
				if (typeOf(values[z]) != 'number') values[z] = scrollSize[z] - size[z];
				values[z] += offset[z];
			}

			return [values.x, values.y];
		},

		toTop: function(){
			return this.start.apply(this, this.calculateScroll(false, 0));
		},

		toLeft: function(){
			return this.start.apply(this, this.calculateScroll(0, false));
		},

		toRight: function(){
			return this.start.apply(this, this.calculateScroll('right', false));
		},

		toBottom: function(){
			return this.start.apply(this, this.calculateScroll(false, 'bottom'));
		},

		toElement: function(el, axes){
			axes = axes ? Array.from(axes) : ['x', 'y'];
			var scroll = isBody(this.element) ? {x: 0, y: 0} : this.element.getScroll();
			var position = Object.map(document.id(el).getPosition(this.element), function(value, axis){
				return axes.contains(axis) ? value + scroll[axis] : false;
			});
			return this.start.apply(this, this.calculateScroll(position.x, position.y));
		},

		toElementEdge: function(el, axes, offset){
			axes = axes ? Array.from(axes) : ['x', 'y'];
			el = document.id(el);
			var to = {},
				position = el.getPosition(this.element),
				size = el.getSize(),
				scroll = this.element.getScroll(),
				containerSize = this.element.getSize(),
				edge = {
					x: position.x + size.x,
					y: position.y + size.y
				};

			['x', 'y'].each(function(axis){
				if (axes.contains(axis)){
					if (edge[axis] > scroll[axis] + containerSize[axis]) to[axis] = edge[axis] - containerSize[axis];
					if (position[axis] < scroll[axis]) to[axis] = position[axis];
				}
				if (to[axis] == null) to[axis] = scroll[axis];
				if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
			}, this);

			if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
			return this;
		},

		toElementCenter: function(el, axes, offset){
			axes = axes ? Array.from(axes) : ['x', 'y'];
			el = document.id(el);
			var to = {},
				position = el.getPosition(this.element),
				size = el.getSize(),
				scroll = this.element.getScroll(),
				containerSize = this.element.getSize();

			['x', 'y'].each(function(axis){
				if (axes.contains(axis)){
					to[axis] = position[axis] - (containerSize[axis] - size[axis]) / 2;
				}
				if (to[axis] == null) to[axis] = scroll[axis];
				if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
			}, this);

			if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
			return this;
		}

	});

	//<1.2compat>
	Fx.Scroll.implement({
		scrollToCenter: function(){
			return this.toElementCenter.apply(this, arguments);
		},
		scrollIntoView: function(){
			return this.toElementEdge.apply(this, arguments);
		}
	});
	//</1.2compat>

	function isBody(element){
		return (/^(?:body|html)$/i).test(element.tagName);
	}

	})();

// mdb: reclaim $ from jquery.
q$ = document.id;




// mootools-more-1.4.0.1.js

// MooTools: the javascript framework.
// Load this file's selection again by visiting: http://mootools.net/more/417ab68a672f38ea1c04efab47af2ff7 
// Or build this file again with packager using: packager build More/Assets
/*
---

script: More.js

name: More

description: MooTools More

license: MIT-style license

authors:
  - Guillermo Rauch
  - Thomas Aylott
  - Scott Kyle
  - Arian Stolwijk
  - Tim Wienk
  - Christoph Pojer
  - Aaron Newton
  - Jacob Thornton

requires:
  - Core/MooTools

provides: [MooTools.More]

...
*/

MooTools.More = {
	'version': '1.4.0.1',
	'build': 'a4244edf2aa97ac8a196fc96082dd35af1abab87'
};


/*
---

script: Assets.js

name: Assets

description: Provides methods to dynamically load JavaScript, CSS, and Image files into the document.

license: MIT-style license

authors:
  - Valerio Proietti

requires:
  - Core/Element.Event
  - /MooTools.More

provides: [Assets]

...
*/

var Asset = {

	javascript: function(source, properties){
		if (!properties) properties = {};

		var script = new Element('script', {src: source, type: 'text/javascript'}),
			doc = properties.document || document,
			load = properties.onload || properties.onLoad;

		delete properties.onload;
		delete properties.onLoad;
		delete properties.document;

		if (load){
			if (typeof script.onreadystatechange != 'undefined'){
				script.addEvent('readystatechange', function(){
					if (['loaded', 'complete'].contains(this.readyState)) load.call(this);
				});
			} else {
				script.addEvent('load', load);
			}
		}

		return script.set(properties).inject(doc.head);
	},

	css: function(source, properties){
		if (!properties) properties = {};

		var link = new Element('link', {
			rel: 'stylesheet',
			media: 'screen',
			type: 'text/css',
			href: source
		});

		var load = properties.onload || properties.onLoad,
			doc = properties.document || document;

		delete properties.onload;
		delete properties.onLoad;
		delete properties.document;

		if (load) link.addEvent('load', load);
		return link.set(properties).inject(doc.head);
	},

	image: function(source, properties){
		if (!properties) properties = {};

		var image = new Image(),
			element = document.id(image) || new Element('img');

		['load', 'abort', 'error'].each(function(name){
			var type = 'on' + name,
				cap = 'on' + name.capitalize(),
				event = properties[type] || properties[cap] || function(){};

			delete properties[cap];
			delete properties[type];

			image[type] = function(){
				if (!image) return;
				if (!element.parentNode){
					element.width = image.width;
					element.height = image.height;
				}
				image = image.onload = image.onabort = image.onerror = null;
				event.delay(1, element, element);
				element.fireEvent(name, element, 1);
			};
		});

		image.src = element.src = source;
		if (image && image.complete) image.onload.delay(1);
		return element.set(properties);
	},

	images: function(sources, options){
		sources = Array.from(sources);

		var fn = function(){},
			counter = 0;

		options = Object.merge({
			onComplete: fn,
			onProgress: fn,
			onError: fn,
			properties: {}
		}, options);

		return new Elements(sources.map(function(source, index){
			return Asset.image(source, Object.append(options.properties, {
				onload: function(){
					counter++;
					options.onProgress.call(this, counter, index, source);
					if (counter == sources.length) options.onComplete();
				},
				onerror: function(){
					counter++;
					options.onError.call(this, counter, index, source);
					if (counter == sources.length) options.onComplete();
				}
			}));
		}));
	}

};





// PageFlavor.js

// functions similar to Java enum.
var PageFlavorItem = (function () {
    function PageFlavorItem(n) {
        this._name = n;
        PageFlavor._instances.push(this);
        if (n == Pageparams.strPageFlavor)
            PageFlavor._curPageFlavor = this;
    }
    return PageFlavorItem;
}());
var PageFlavor = (function () {
    function PageFlavor() {
    }
    PageFlavor.init = function () {
        if (PageFlavor._instances.length > 0)
            return;
        // We expect one call to PlageFlavorItem constructor to discover
        // a matching Pageparams.strPageFlavor and set _curPageFlavor according.
        PageFlavor.QPlayerDesk = new PageFlavorItem("QPlayerDesk");
        PageFlavor.QPlayerApp = new PageFlavorItem("QPlayerApp");
        PageFlavor.QPlayerMoBr = new PageFlavorItem("QPlayerMoBr");
        PageFlavor.WPlayerDesk = new PageFlavorItem("WPlayer");
        PageFlavor.WPlayerMoBr = new PageFlavorItem("WPlayerMoBr");
        PageFlavor.SPlayerDesk = new PageFlavorItem("SPlayerDesk");
        PageFlavor.SPlayerMoBr = new PageFlavorItem("SPlayerMoBr");
        PageFlavor.SPlayerApp = new PageFlavorItem("SPlayerApp");
        PageFlavor.SPlayerAppReg = new PageFlavorItem("SPlayerAppReg");
        PageFlavor.QMoBr = new PageFlavorItem("QMoBr");
        PageFlavor.Other = new PageFlavorItem("Other");
        if (!PageFlavor._curPageFlavor) {
            // this isn't supposed to happen
            PageFlavor._curPageFlavor = PageFlavor.Other;
        }
    };
    PageFlavor.isFlavor = function (flavor) {
        if (typeof (flavor) == 'string') {
            return (flavor == PageFlavor._curPageFlavor._name);
        }
        return flavor == PageFlavor._curPageFlavor;
    };
    PageFlavor.isSPlayerFamily = function () {
        // for Univadis, including Univadis APP?
        if (PageFlavor._curPageFlavor == PageFlavor.SPlayerDesk ||
            PageFlavor._curPageFlavor == PageFlavor.SPlayerMoBr ||
            PageFlavor._curPageFlavor == PageFlavor.SPlayerApp) {
            return true;
        }
        return false;
    };
    PageFlavor.isMoBr = function () {
        if (PageFlavor._curPageFlavor == PageFlavor.QPlayerMoBr ||
            PageFlavor._curPageFlavor == PageFlavor.SPlayerMoBr ||
            PageFlavor._curPageFlavor == PageFlavor.WPlayerMoBr ||
            PageFlavor._curPageFlavor == PageFlavor.QMoBr) {
            return true;
        }
        return false;
    };
    PageFlavor.isFromApp = function () {
        if (PageFlavor._curPageFlavor == PageFlavor.QPlayerApp ||
            PageFlavor._curPageFlavor == PageFlavor.SPlayerApp) {
            return true;
        }
        return false;
    };
    PageFlavor.isMoBrWithPanels = function () {
        if (PageFlavor._curPageFlavor == PageFlavor.QPlayerMoBr ||
            PageFlavor._curPageFlavor == PageFlavor.WPlayerMoBr) {
            return true;
        }
        return false;
    };
    PageFlavor.isMoBrWithOutPanels = function () {
        if (PageFlavor._curPageFlavor == PageFlavor.SPlayerMoBr ||
            PageFlavor._curPageFlavor == PageFlavor.SPlayerApp) {
            return true;
        }
        return false;
    };
    PageFlavor.isDesktop = function () {
        return (PageFlavor._curPageFlavor == PageFlavor.QPlayerDesk);
    };
    PageFlavor.shouldShowRegOrLogin = function () {
        // FIXME -- re-implement based on explicit flavor
        var url = location.href.toLowerCase();
        var specialPlayers = ["/piplayer", "/wplayer", "/splayer", "/service"];
        for (var i = 0; i < specialPlayers.length; i++) {
            if (url.indexOf(specialPlayers[i]) >= 0) {
                return false;
            }
        }
        return true;
    };
    PageFlavor.expectsMobileAjax = function () {
        if (PageFlavor._curPageFlavor == PageFlavor.QPlayerApp)
            return true;
        return false;
    };
    PageFlavor._instances = [];
    return PageFlavor;
}());
PageFlavor.init();




// QUtils.js

/// <reference path="Window.d.ts" />
// See http://en.wikipedia.org/wiki/Plane_%28Unicode%29#Basic_Multilingual_Plane
// for detecting emojis and other characters that MySQL's utf8 can't handle
function containsNonBasicMultilingualCharacter(str) {
    var len = str.length;
    for (var i = 0; i < len; ++i) {
        var code = str.charCodeAt(i);
        if (0xD800 <= code && code <= 0xDBFF) {
            return true;
        }
    }
    return false;
}
function str_repeat(i, m) {
    var o = [];
    while (m > 0) {
        o[--m] = i;
    }
    return (o.join(''));
}
function sprintf() {
    var args = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
    }
    var o = [];
    var i = 0;
    var f = args[i++];
    var a, m, p, c, x;
    while (f) {
        if ((m = /^[^\x25]+/.exec(f)))
            o.push(m[0]);
        else if ((m = /^\x25{2}/.exec(f)))
            o.push('%');
        else if ((m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f))) {
            if (((a = arguments[m[1] || i++]) === null) || (a === undefined))
                throw ("Too few arguments.");
            /*if (/[^s]/.test(m[7]) && (typeof(a) != 'number'))
             throw("Expecting number but found " + typeof(a));*/
            switch (m[7]) {
                case 'b':
                    a = a.toString(2);
                    break;
                case 'c':
                    a = String.fromCharCode(a);
                    break;
                case 'd':
                    a = parseInt(a, 10); // specify radix to avoid bugs with "010" being read as octal
                    break;
                case 'e':
                    a = m[6] ? a.toExponential(m[6]) : a.toExponential();
                    break;
                case 'f':
                    a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a);
                    break;
                case 'o':
                    a = a.toString(8);
                    break;
                case 's':
                    a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a);
                    break;
                case 'u':
                    a = Math.abs(a);
                    break;
                case 'x':
                    a = a.toString(16);
                    break;
                case 'X':
                    a = a.toString(16).toUpperCase();
                    break;
                default:
                    throw ("Unknown sprintf type " + m[7]);
            }
            a = (/[def]/.test(m[7]) && m[2] && a > 0 ? '+' + a : a);
            c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';
            x = m[5] - String(a).length;
            p = m[5] ? str_repeat(c, x) : '';
            o.push(m[4] ? a + p : p + a);
        }
        else
            throw ("Huh ?!");
        f = f.substring(m[0].length);
    }
    return o.join('');
}
function getNamedObject(objName) {
    if (window.document[objName]) {
        return window.document[objName];
    }
    if (navigator.appName.indexOf("Microsoft Internet") === -1) {
        if (document.embeds && document.embeds[objName])
            return document.embeds[objName];
    }
    else {
        return document.getElementById(objName);
    }
}
function getDateDifference(startingDateMs) {
    if (startingDateMs === null)
        return "";
    var currentTime = new Date();
    try {
        currentTime = Common.currentDfInPlayer().calcCurrentServerTime();
    }
    catch (e) { }
    var difference = currentTime.getTime() - startingDateMs;
    var seconds = Math.floor(difference / 1000);
    var minutes = Math.floor(seconds / 60);
    var hours = Math.floor(minutes / 60);
    var days = Math.floor(hours / 24);
    if (difference < 0) {
        return QSTR.momentsAgo;
    }
    if (difference < 60 * 1000) {
        if (seconds === 1) {
            return QSTR.secondAgo;
        }
        return sprintf(QSTR.secondsAgo, seconds);
    }
    if (difference < 60 * 60 * 1000) {
        if (minutes === 1) {
            return QSTR.minuteAgo;
        }
        return sprintf(QSTR.minutesAgo, minutes);
    }
    if (difference < 24 * 60 * 60 * 1000) {
        if (hours === 1) {
            return QSTR.hourAgo;
        }
        return sprintf(QSTR.hoursAgo, hours);
    }
    if (days === 1) {
        return QSTR.dayAgo;
    }
    if (days > 30) {
        return ""; //we don't show anything if over 30 days.
    }
    return sprintf(QSTR.daysAgo, days);
}
function getCommentDateDifference(objWithServerTime, numberOfComments, startingDateMs, zeroIsOkay) {
    if ((numberOfComments === 0) || !numberOfComments || !objWithServerTime) {
        if (!zeroIsOkay)
            return "";
    }
    if (startingDateMs === null) {
        var restag = (numberOfComments === 1) ? QSTR.lastComment : QSTR.lastComments;
        return sprintf(restag, numberOfComments);
    }
    var currentTime = new Date();
    try {
        currentTime = objWithServerTime.calcCurrentServerTime();
    }
    catch (e) { }
    var difference = currentTime.getTime() - startingDateMs;
    var seconds = Math.floor(difference / 1000);
    var minutes = Math.floor(seconds / 60);
    var hours = Math.floor(minutes / 60);
    var days = Math.floor(hours / 24);
    // we don't want to show "heat" if there is no comment within the past 30 days... just show the number of comments
    if (days > 30) {
        if (numberOfComments === 1) {
            return sprintf(QSTR.lastComment, numberOfComments);
        }
        else {
            return sprintf(QSTR.lastComments, numberOfComments);
        }
    }
    if (numberOfComments == 1) {
        if (difference < 0) {
            return sprintf(QSTR.lastCommentMomentsAgo, numberOfComments);
        }
        if (difference < 60 * 1000) {
            if (seconds === 1) {
                return sprintf(QSTR.lastCommentSecondAgo, numberOfComments);
            }
            return sprintf(QSTR.lastCommentSecondsAgo, numberOfComments, seconds);
        }
        if (difference < 60 * 60 * 1000) {
            if (minutes == 1) {
                return sprintf(QSTR.lastCommentMinuteAgo, numberOfComments);
            }
            return sprintf(QSTR.lastCommentMinutesAgo, numberOfComments, minutes);
        }
        if (difference < 24 * 60 * 60 * 1000) {
            if (hours === 1) {
                return sprintf(QSTR.lastCommentHourAgo, numberOfComments);
            }
            return sprintf(QSTR.lastCommentHoursAgo, numberOfComments, hours);
        }
        if (days === 1) {
            return sprintf(QSTR.lastCommentDayAgo, numberOfComments);
        }
        return sprintf(QSTR.lastCommentDaysAgo, numberOfComments, days);
    }
    else {
        if (difference < 0) {
            return sprintf(QSTR.lastCommentsMomentsAgo, numberOfComments);
        }
        if (difference < 60 * 1000) {
            if (seconds == 1) {
                return sprintf(QSTR.lastCommentsSecondAgo, numberOfComments);
            }
            return sprintf(QSTR.lastCommentsSecondsAgo, numberOfComments, seconds);
        }
        if (difference < 60 * 60 * 1000) {
            if (minutes == 1) {
                return sprintf(QSTR.lastCommentsMinuteAgo, numberOfComments);
            }
            return sprintf(QSTR.lastCommentsMinutesAgo, numberOfComments, minutes);
        }
        if (difference < 24 * 60 * 60 * 1000) {
            if (hours == 1) {
                return sprintf(QSTR.lastCommentsHourAgo, numberOfComments);
            }
            return sprintf(QSTR.lastCommentsHoursAgo, numberOfComments, hours);
        }
        if (days === 1) {
            return sprintf(QSTR.lastCommentsDayAgo, numberOfComments);
        }
        return sprintf(QSTR.lastCommentsDaysAgo, numberOfComments, days);
    }
}
function getCommentDateDifferenceShort(objWithServerTime, numberOfComments, startingDateMs) {
    var caption = QSTR.mobileComments;
    var commentStr = QSTR.commentLowerInitial;
    var commentsStr = QSTR.commentsLowerInitial;
    var commaSpace = QSTR.commaSeparator;
    var lastStr = QSTR.commentLast + " ";
    if (!numberOfComments || !objWithServerTime) {
        return caption;
    }
    if (startingDateMs === null) {
        return numberOfComments + " " + ((numberOfComments === 1) ? commentStr : commentsStr);
    }
    var currentTime = new Date();
    try {
        currentTime = objWithServerTime.calcCurrentServerTime();
    }
    catch (e) {
    }
    var msDiff = currentTime.getTime() - startingDateMs;
    var seconds = Math.floor(msDiff / 1000);
    var minutes = Math.floor(seconds / 60);
    var hours = Math.floor(minutes / 60);
    var days = Math.floor(hours / 24);
    // we don't want to show "heat" if there is no comment within the past 30 days... just show the number of comments
    if (days > 30) {
        return numberOfComments + " " + ((numberOfComments === 1) ? commentStr : commentsStr);
    }
    if (numberOfComments == 1) {
        caption = numberOfComments + " " + commentStr + commaSpace + lastStr;
    }
    else {
        caption = numberOfComments + " " + commentsStr + commaSpace + lastStr;
    }
    if (msDiff <= 1000) {
        return caption + QSTR.commentMomentsAgo;
    }
    if (msDiff < 60 * 1000) {
        return caption + seconds + " " + QSTR.commentSecondsAgo;
    }
    if (msDiff < 60 * 60 * 1000) {
        return caption + minutes + " " + QSTR.commentMinutesAgo;
    }
    if (msDiff < 24 * 60 * 60 * 1000) {
        return caption + hours + " " + QSTR.commentHoursAgo;
    }
    if (days === 1) {
        return caption + days + " " + QSTR.commentDayAgo;
    }
    return caption + days + " " + QSTR.commentDaysAgo;
}
function refreshTimeZone() {
    setTimeout(storeTimeZone, 20000);
}
function storeTimeZone() {
    var tz = new Date().getTimezoneOffset() * -1;
    createCookie("com.quantia.tz", "" + tz, 0);
}
/**
 * Returns cookie value if cookie exists and has a non-empty value,
 * otherwise returns null
 */
function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    var result = null;
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) === ' ')
            c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) === 0) {
            // if there already is a cookie found, that means that there must be two cookies on two separate domains...
            // and that is bad.  so clear the one that doesn't have a domain specified.
            if (result !== null) {
                var date = new Date();
                date.setTime(date.getTime() + (-1 * 24 * 60 * 60 * 1000));
                var expires = "; expires=" + date.toUTCString();
                //alert("bad Place");
                document.cookie = name + "=" + expires + "; path=/";
            }
            result = c.substring(nameEQ.length, c.length);
        }
    }
    if ('' === result)
        result = null;
    return result;
}
function deleteCookie(name) {
    // create with these args will cause a deletion
    createCookie(name, "", -1);
}
function createCookie(name, value, days, secure) {
    var domain, expires = "", pieces, plen;
    if (secure === undefined)
        secure = false;
    if (days) {
        var date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        expires = "; expires=" + date.toUTCString();
    }
    var sn = gQCredentials.getServerName();
    var sec = (secure ? ";secure" : "");
    var path = "";
    if (sn !== null && sn.indexOf("quantiamd.com") > -1) {
        path = "; path=/;domain=quantiamd.com";
    }
    else if (sn !== null && sn.indexOf("univadis.com") > -1) {
        path = "; path=/;domain=univadis.com";
    }
    else if (sn !== null && sn.indexOf("quantiaco.com") > -1) {
        pieces = gQCredentials.getServerName().split(".");
        plen = pieces.length;
        path = "; path=/;domain=" + pieces[plen - 3] + ".quantiaco.com";
    }
    else if (sn === 'localhost') {
        path = "; path=/";
    }
    else {
        domain = sn.replace(/secure\./, '');
        path = "; path=/;domain=" + domain;
    }
    document.cookie = name + "=" + value + expires + path + sec;
    // if this is clearing the cookie, make sure we reset it for the default path as well
    if ((value === "") && (days < 0)) {
        document.cookie = name + "=" + value + expires + "; path=/";
    }
}
function makeHtmlRespectingNewlinesAndSpaces(text) {
    text = text.replace(/\n\n/g, "\n");
    text = text.replace(/\n /g, "<p class='indentedP'></p>&nbsp;");
    text = text.replace(/\n/g, "<p class='userContentP'></p>"); // single-newlines should just start new paragraphs
    text = text.replace(/  /g, "&nbsp; "); // double space to non-breaking space plus space, iteratively
    return text;
}
function truncateCommentPanelTitleByRounds(commentPanelTitle, rounds) {
    if (rounds == 1)
        return commentPanelTitle;
    var lastPos = commentPanelTitle.indexOf(QSTR.commentLast);
    if (rounds == 2 && lastPos > 0)
        return commentPanelTitle.substr(0, lastPos + QSTR.commentLast.length) + "...";
    var commaPos = commentPanelTitle.indexOf(QSTR.commaSeparator);
    if (rounds == 3 && commaPos > 0)
        return commentPanelTitle.substr(0, commaPos) + "...";
    return commentPanelTitle;
}
function replaceUrlTokens(url) {
    if (url.indexOf('{') == -1)
        return url;
    var qsclUrlReplacements = {
        "{UserCode}": gQCredentials.UserCode,
        "{FirstName}": AccountInfo.FirstName,
        "{LastName}": AccountInfo.LastName,
        "{dfid}": Common.currentDFID()
    };
    var regex = new RegExp("(\{[^\{\}]*\})");
    var result;
    do {
        result = regex.exec(url);
        if (result) {
            var index = result.index;
            var token = result[0];
            var newValue = qsclUrlReplacements[token];
            if (newValue) {
                newValue = encodeURIComponent(newValue);
                newValue = newValue.replace(' ', '+');
                url = url.replace(token, newValue);
            }
        }
    } while (result);
    return url;
}




// UnsupportedBrowserDialog.js

/// <reference path="mootools.d.ts" />
/// <reference path="Common.d.ts" />
var UnsupportedBrowserDialog = (function () {
    function UnsupportedBrowserDialog() {
    }
    UnsupportedBrowserDialog.show = function () {
        AfterStartupEvents.registerAfterStartup(UnsupportedBrowserDialog.showOnPageLoad);
    };
    UnsupportedBrowserDialog.showOnPageLoad = function () {
        var dlg = q$('ie8Dialog');
        if (!dlg)
            return;
        var cookieVal = readCookie(UnsupportedBrowserDialog.viewedCookieName);
        if (!cookieVal) {
            dlg.removeClass('hiddenDialog');
            DialogUtils.removeBodyScrollBars();
            window.addEvent('resize', UnsupportedBrowserDialog.handleResize);
            UnsupportedBrowserDialog.handleResize();
        }
    };
    UnsupportedBrowserDialog.showHelp = function () {
        UnsupportedBrowserDialog.hide();
        Common.openMemberHelp();
    };
    UnsupportedBrowserDialog.hide = function () {
        var dlg = q$('ie8Dialog');
        if (!dlg)
            return;
        createCookie(UnsupportedBrowserDialog.viewedCookieName, "true"); // session cookie
        DialogUtils.restoreBodyScrollBars();
        dlg.addClass('hiddenDialog');
    };
    UnsupportedBrowserDialog.handleResize = function () {
        var innerDialog = q$('innerIE8Dialog');
        var bg = q$('ie8Background');
        DialogUtils.handleDialogResize(innerDialog, bg);
    };
    UnsupportedBrowserDialog.viewedCookieName = 'com.quantia.ie8';
    return UnsupportedBrowserDialog;
}());




// XML.js

var XML = (function () {
    function XML() {
    }
    XML.CreateDocument = function (strXml) {
        try {
            return (new DOMParser()).parseFromString(strXml, "text/xml");
        }
        catch (e) {
        }
        try {
            var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.loadXML(strXml);
            return xmlDoc;
        }
        catch (e) {
        }
    };
    XML.MakeSureDocumentIsNormalized = function (xmlDoc) {
        if (typeof window['gecko'] != 'undefined') {
            if (xmlDoc && !xmlDoc.hasBeenNormalized) {
                xmlDoc.hasBeenNormalized = true;
                xmlDoc.normalize();
            }
        }
    };
    XML.getElementsByTagNameOneLevel = function (xmlElem, strValue) {
        XML.MakeSureDocumentIsNormalized(xmlElem);
        if (!xmlElem.childNodes)
            return null;
        var results = [];
        var j = 0;
        var childCount = xmlElem.childNodes.length;
        for (var i = 0; i < childCount; ++i) {
            var child = xmlElem.childNodes[i];
            if (child.nodeName == strValue) {
                results[j++] = child;
            }
        }
        return results;
    };
    XML.getElementByTagNameOneLevel = function (xmlElem, strValue) {
        XML.MakeSureDocumentIsNormalized(xmlElem);
        if (xmlElem["childNodes"]) {
            var childCount = xmlElem.childNodes.length;
            for (var i = 0; i < childCount; ++i) {
                var child = xmlElem.childNodes[i];
                if (child.nodeName == strValue) {
                    return child;
                }
            }
        }
        return null;
    };
    XML.findAndFillValueOneLevel = function (xmlElem, strValue) {
        var i;
        XML.MakeSureDocumentIsNormalized(xmlElem);
        try {
            var tmp = null;
            if (!strValue) {
                tmp = xmlElem;
            }
            else {
                tmp = null;
                for (i = 0; i < xmlElem.childNodes.length; i++) {
                    var childElt = xmlElem.childNodes[i];
                    if (childElt.nodeName == strValue) {
                        tmp = childElt;
                        break;
                    }
                }
            }
            if (tmp) {
                var result = "";
                for (i = 0; i < tmp.childNodes.length; i++) {
                    var child = tmp.childNodes[i];
                    if (child.nodeType == 3) {
                        // if it's a text node
                        result += child.nodeValue;
                    }
                }
                return result;
            }
        }
        catch (e) {
        }
        return "";
    };
    XML.findAndFillValue = function (xmlElem, strValue, unescapeText) {
        XML.MakeSureDocumentIsNormalized(xmlElem);
        try {
            var tmp = (!strValue) ? xmlElem : XML.getFirstElementByTagName(xmlElem, strValue);
            if (tmp) {
                var result = "";
                for (var i = 0; i < tmp.childNodes.length; i++) {
                    var child = tmp.childNodes[i];
                    if ((child.nodeType == 3) ||
                        (child == 4)) {
                        result += child.nodeValue;
                    }
                }
                if (unescapeText) {
                    return unescape(result);
                }
                return result;
            }
        }
        catch (e) {
        }
        return "";
    };
    XML.SetNodeValue = function (xmlElem, strValue) {
        var tmp2 = xmlElem.childNodes[0];
        tmp2.nodeValue = strValue;
    };
    XML.findAndFillValueInt = function (xmlElem, strValue) {
        XML.MakeSureDocumentIsNormalized(xmlElem);
        try {
            var strRes = XML.findAndFillValue(xmlElem, strValue);
            if (strRes.length > 0) {
                return parseInt(strRes, 10);
            }
        }
        catch (e) {
        }
        return -1;
    };
    XML.findAndFillValueFloat = function (xmlElem, strValue) {
        XML.MakeSureDocumentIsNormalized(xmlElem);
        try {
            var strRes = XML.findAndFillValue(xmlElem, strValue);
            if (strRes.length > 0) {
                return parseFloat(strRes);
            }
        }
        catch (e) {
        }
        return -1.0;
    };
    XML.findAndFillValueBool = function (xmlElem, strValue) {
        XML.MakeSureDocumentIsNormalized(xmlElem);
        try {
            var strRes = XML.findAndFillValue(xmlElem, strValue);
            if (strRes == "true") {
                return true;
            }
            if (strRes == "false") {
                return false;
            }
        }
        catch (e) {
        }
        return null;
    };
    XML.getAttributeFromTag = function (xmlElem, strTagName, strAttributeName, defaultValue) {
        XML.MakeSureDocumentIsNormalized(xmlElem);
        try {
            //given an XML node/element, finds the tag within the node,
            //then finds the specified attribute of that tag
            //eg. if you want to find value from qpoint, strTagName = qpoint,
            //strAttributeName = value;
            //<qpoint value="3.5" qp_edts="" qp_id="1" />
            var tmp = XML.getFirstElementByTagName(xmlElem, strTagName);
            if (tmp) {
                var tmp2 = tmp.getAttribute(strAttributeName);
                if (tmp2) {
                    return tmp2;
                }
            }
        }
        catch (e) {
        }
        if (!defaultValue) {
            defaultValue = "";
        }
        return defaultValue;
    };
    XML.getFirstElementByTagName = function (xmlElem, strTagName) {
        XML.MakeSureDocumentIsNormalized(xmlElem);
        try {
            var elemList = XML.getElementsByTagName(xmlElem, strTagName);
            if (elemList)
                return elemList[0];
        }
        catch (e) {
        }
        return null;
    };
    XML.getFirstElementByTagNameOneLevel = function (xmlElem, strTagName) {
        XML.MakeSureDocumentIsNormalized(xmlElem);
        try {
            var elemList = XML.getElementsByTagName(xmlElem, strTagName);
            if (elemList) {
                for (var i = 0; i < elemList.length; i++) {
                    var elem = elemList[i];
                    if (elem.parentNode == xmlElem) {
                        return elem;
                    }
                }
            }
        }
        catch (e) {
        }
        return null;
    };
    XML.getElementsByTagName = function (xmlElem, strTagName) {
        XML.MakeSureDocumentIsNormalized(xmlElem);
        try {
            var elemList = xmlElem.getElementsByTagName(strTagName);
            if (elemList && elemList.length > 0) {
                return elemList;
            }
        }
        catch (e) {
        }
        return null;
    };
    XML.serialize = function (node) {
        if (typeof XMLSerializer != "undefined")
            try {
                return (new XMLSerializer()).serializeToString(node);
            }
            catch (e) {
            }
        else if (node.xml)
            return node.xml;
        else
            alert("XML.Serialize is not supported or can't serialize " + node);
    };
    XML.doesSerializeEscapeBadChars = function () {
        if (XML._doesSerializeEscapeBadChars === null) {
            //  build a a document with a bad char and see what happens
            var xmlDoc = XML.CreateDocument("<x></x>");
            var yElem = xmlDoc.createElement("y");
            yElem.appendChild(xmlDoc.createTextNode("<"));
            xmlDoc.documentElement.appendChild(yElem);
            XML._doesSerializeEscapeBadChars = (XML.serialize(xmlDoc).indexOf("<x><y>&lt;</y></x>") > -1);
        }
        return (XML._doesSerializeEscapeBadChars);
    };
    XML.CreateTextNode = function (xmlDoc, strText) {
        if (!XML.doesSerializeEscapeBadChars()) {
            strText = XML.RemoveBadXMLCharacters(strText);
        }
        return xmlDoc.createTextNode(strText);
    };
    XML.RemoveBadXMLCharacters = function (strText) {
        strText = strText.replace(/&/g, "&amp;");
        strText = strText.replace(/</g, "&lt;");
        strText = strText.replace(/>/g, "&gt;");
        return strText;
    };
    XML.addXmlChild = function (parent, xmlDocument, name, value) {
        if ((value === null) || (value === '') || (typeof value === 'undefined')) {
            return;
        }
        var element = xmlDocument.createElement(name);
        element.appendChild(XML.CreateTextNode(xmlDocument, value));
        parent.appendChild(element);
    };
    XML._doesSerializeEscapeBadChars = null;
    return XML;
}());




// SoftPlayerControls.js

/// <reference path="Common.d.ts" />
/// <reference path="panels2/PanelName.ts" />
/// <reference path="jsMobile/player.ts" />
var SoftPlayerControls = (function () {
    function SoftPlayerControls() {
    }
    SoftPlayerControls.setHidden = function (v) {
        SoftPlayerControls.isHidden = v;
    };
    SoftPlayerControls.autoHide = function () {
        if (Common.screenHasVariableHeight(PageLayout.currentScreenType))
            return;
        var softpc = q$('softPlayerControls');
        Common.chide(softpc);
        PageLayout.showLandscapeResizeControl(false);
        SoftPlayerControls.isHidden = true;
        if (Common.isIOS()) {
            player.onResizePlayer();
        }
        else {
            PlayerWrapper.bringVideoBackToFront();
        }
        if (Common.screenIsVideo(PageLayout.currentScreenType)) {
            if (!PageFlavor.isMoBr()) {
                q$('screenHost').style.pointerEvents = 'none';
            }
        }
    };
    SoftPlayerControls.scheduleAutoHide = function (msDelay) {
        SoftPlayerControls.clearAutoHide();
        SoftPlayerControls.autoHideTimer = setTimeout(SoftPlayerControls.autoHide, msDelay);
    };
    SoftPlayerControls.clearAutoHide = function () {
        clearTimeout(SoftPlayerControls.autoHideTimer);
        SoftPlayerControls.autoHideTimer = null;
    };
    SoftPlayerControls.handleTouch = function (skipOnResize, skipAutoHide) {
        // let 'touch' toggle the soft controls
        if (Common.getManualClickMgr().needsClick())
            return;
        var spc = q$('softPlayerControls');
        if (Common.screenHasVariableHeight(PageLayout.currentScreenType)) {
            Common.cshow(spc);
            spc.removeClass('softHidden');
            return;
        }
        if (SoftPlayerControls.isHidden) {
            Common.cshow(spc);
            PageLayout.hideLandscapeResizeControl();
            if (!(PageLayout.currentScreenType == 'ActionListScreen')) {
                PageLayout.MovePlayPauseToCenter();
            }
            else {
                PageLayout.MovePlayPauseToNormalPosition();
                if (PageLayout.currentLayout == Arrangement.LAY_MOBILE_PORTRAIT_2014) {
                    PageLayout.moveSecondPanelOffscreen();
                    PageLayout.expandMainPanelCntToFullScreen();
                }
            }
            SoftPlayerControls.isHidden = false;
            SoftPlayerControls.clearAutoHide();
            if (typeof skipAutoHide === "undefined" || !skipAutoHide) {
                SoftPlayerControls.autoHideTimer = setTimeout(SoftPlayerControls.autoHide, 3000);
            }
        }
        else if (!SoftPlayerControls.isHidden) {
            if (!(Common.screenHasVariableHeight(PageLayout.currentScreenType))) {
                Common.chide(spc);
            }
            PageLayout.showLandscapeResizeControl(false);
            SoftPlayerControls.isHidden = true;
            if (Common.isIOS()) {
                player.onResizePlayer();
            }
            else {
                PlayerWrapper.bringVideoBackToFront();
            }
            if (Common.screenIsVideo(PageLayout.currentScreenType)) {
                if (!PageFlavor.isMoBr()) {
                    q$('screenHost').style.pointerEvents = 'none';
                }
            }
        }
        var playerPanel = PanelManager.getPanelByID(PanelName.player);
        playerPanel.Recompute(skipOnResize);
    };
    SoftPlayerControls.showFromMobileWebPlayer = function () {
        var spc = q$('softPlayerControls');
        if (Common.ischidden(spc)) {
            Common.cshow(spc);
            spc.removeClass('softHidden');
            if (MobilePlayerVer.isLatest()) {
                SoftPlayerControls.handleTouch(true, true);
            }
        }
    };
    SoftPlayerControls.hideOrShowSoftControls = function (bHide) {
        var spc = q$('softPlayerControls');
        if (!spc)
            return;
        if (bHide) {
            var backNextCtrls = BackNextControlsBase.current;
            if (ScreenLayout.current == ScreenLayout.SHOWTITLE ||
                (backNextCtrls && backNextCtrls.CurrentNextState == BackNextControlsBase.NEXTSTATE_NEXT_HIGHLIGHT)) {
                Common.cshow(spc);
                var hideSoftCtrls = MobilePlayerVer.is2010();
                spc.toggleClass('softHidden', hideSoftCtrls);
            }
            else {
                if (!(MobilePlayerVer.isLatest() && PageLayout.currentScreenType == 'ActionListScreen')) {
                    Common.chide(spc);
                }
                spc.removeClass('softHidden');
            }
        }
        else {
            Common.cshow(spc);
            spc.removeClass('softHidden');
        }
    };
    SoftPlayerControls.hide = function () {
        Common.chide('softPlayerControls');
    };
    SoftPlayerControls.show = function () {
        Common.cshow('softPlayerControls');
    };
    SoftPlayerControls.hideCtrl = function (ctrlID) {
    };
    SoftPlayerControls.showCtrl = function (ctrlID) {
    };
    SoftPlayerControls.updateSize = function (aPlayerElt, width, height) {
        var spc = q$('softPlayerControls');
        var controlsSize = 0;
        if (!spc)
            return controlsSize;
        controlsSize = spc.getSize().y;
        var spacing = PageLayout.playerExtraSpacing();
        if (controlsSize > 0) {
            var controlsWidth = (MobilePlayerVer.isLatest()) ?
                (width + Math.floor(spacing) * 2) :
                (width + spacing * 2);
            spc.setStyle('width', controlsWidth + 'px');
            var controlsTop = (MobilePlayerVer.isLatest()) ?
                (height - controlsSize) :
                (height - controlsSize + 1);
            spc.setStyle('top', controlsTop + 'px');
            spc.setStyle('margin-left', -(spacing) + 'px');
        }
        if (spc.hasClass('cHidden') || spc.hasClass("softHidden")) {
            controlsSize = -2;
            aPlayerElt.removeClass('controlsVisible');
        }
        else {
            aPlayerElt.addClass('controlsVisible');
        }
        var widthInInches = ScreenDim.inchesFromPx(width);
        var firstThreshold = 2.2;
        var secondThreshold = 2.75;
        if (MobilePlayerVer.isLatest()) {
            firstThreshold = 1.2;
        }
        else {
            if (/iPhone|iPod/i.test(navigator.userAgent)) {
                secondThreshold = 3.1;
            }
        }
        if (widthInInches < firstThreshold) {
            spc.removeClass('timeline');
            spc.removeClass('condensedTimeline');
        }
        else if (widthInInches < secondThreshold) {
            spc.addClass('timeline');
            spc.addClass('condensedTimeline');
        }
        else if (widthInInches < 5.9) {
            spc.addClass('timeline');
            spc.removeClass('condensedTimeline');
        }
        else {
            spc.addClass('timeline');
            spc.removeClass('condensedTimeline');
        }
        if (PageLayout.shouldNextAndBackBeOnLeft()) {
            spc.addClass('backNextOnLeft');
            spc.removeClass('backNextOnRight');
        }
        else {
            spc.removeClass('backNextOnLeft');
            spc.addClass('backNextOnRight');
        }
        if (PageLayout.shouldAllowZoom()) {
            if (PageLayout.isZoom()) {
                spc.removeClass('zoomIn');
                spc.addClass('zoomOut');
            }
            else {
                spc.addClass('zoomIn');
                spc.removeClass('zoomOut');
            }
        }
        else {
            spc.removeClass('zoomIn');
            spc.removeClass('zoomOut');
        }
        var _innerControls = q$('innerPlayerControls');
        if (MobilePlayerVer.isLatest()) {
            spc.addClass('softPlayerControls2014');
            _innerControls.removeClass("useMobilePlayerControlsBefore2014");
            _innerControls.addClass("useMobilePlayerControls2014");
        }
        else {
            spc.removeClass('softPlayerControls2014');
            _innerControls.removeClass("useMobilePlayerControls2014");
            _innerControls.addClass("useMobilePlayerControlsBefore2014");
        }
        return controlsSize;
    };
    SoftPlayerControls.autoHideTimer = null;
    SoftPlayerControls.isHidden = true;
    return SoftPlayerControls;
}());




// AfterStartupEvents.js

/// <reference path="Common.d.ts" />
var AfterStartupEventsClass = (function () {
    function AfterStartupEventsClass() {
        this._startupEventsRun = false;
        this._afterStartupEvents = [];
        this._afterDomChangeEvents = [];
    }
    // afterStartup events get one once, either at startup
    // or immediately if registration happans after the startup batch
    // is run.
    AfterStartupEventsClass.prototype.registerAfterStartup = function (fn) {
        if (this._startupEventsRun) {
            try {
                // Common.addDebugStr("AfterStartup immediate f=" + fn.name);
                fn();
            }
            catch (e) {
                Common.addDebugStr("EXC startupEvent fn=" + fn.name + " ex: " + e);
                if (!fn.name)
                    Common.addDebugStr("   fn text =" + fn.toString());
            }
        }
        else {
            this._afterStartupEvents.push(fn);
        }
    };
    // AfterDomChange events can happen multiple times.
    AfterStartupEventsClass.prototype.registerAfterDomChange = function (fn) {
        // Common.addDebugStr("After DomChange immediate f=" + fn.name);
        this._afterDomChangeEvents.push(fn);
    };
    AfterStartupEventsClass.prototype.doAfterDomChange = function () {
        for (var i = 0; i < this._afterDomChangeEvents.length; i++) {
            var fn = this._afterDomChangeEvents[i];
            try {
                // Common.addDebugStr("AfterDomChange fn=" + fn.name);
                fn();
            }
            catch (e) {
                Common.addDebugStr("EXC AfterDomChange fn=" + fn.name + " ex: " + e);
            }
        }
    };
    AfterStartupEventsClass.prototype.doAfterStartup = function () {
        this._startupEventsRun = true;
        for (var i = 0; i < this._afterStartupEvents.length; i++) {
            var fn = this._afterStartupEvents[i];
            try {
                // Common.addDebugStr("After Startup immediate f=" + fn.name);
                fn();
            }
            catch (e) {
                Common.addDebugStr("startupEvent fn=" + fn.name + " ex: " + e);
            }
        }
        this.doAfterDomChange();
    };
    return AfterStartupEventsClass;
}());
var AfterStartupEvents = new AfterStartupEventsClass();
// doOnPageReady
doOnPageReady = function (fn) {
    AfterStartupEvents.registerAfterStartup(fn);
};




// ExternalContract.js

/* ExternalContract.ts
 * These are methods that can potentially be called by the thick-app or other content
 * These functions must be maintained with these signatures.
 */
/// <reference path="../Common.d.ts" />
/// <reference path="../Window.d.ts" />
/// <reference path="../appIFace/AppIFace.d.ts" />
/// <reference path="../jsMobile/ScreenDim.ts" />
/// <reference path="../jsMobile/player.ts" />
// called by thick-bits
function setScreenSize(width, height, dpi, isIPad) {
    // Common.addDebugStr("ExternalContract:setScreenSize w" + width + " h=" + height + " d=" + dpi + " ipad=" + !!isIPad);
    try {
        ScreenDim.SetScreenSize1(width, height, dpi, isIPad);
    }
    catch (e) {
        Common.addDebugStr("EXC ExternalContract:setScreenSize exc=" + e);
    }
}
// viewDataform:  called by html/dataform content; maybe some internal callers as well.
function viewDataform(dfid, ns, isSecure, urlToShowAfter, webUrl, trackingInfo) {
    Common.addDebugStr("ExternalContract:viewDataform " + dfid + " weburl=" + webUrl);
    if (Common.isMobilePlayer()) {
        // We don't normally launch a dataform from the mobile player
        // because we're in a dataform there already... but if we want to
        // launch one dataform from another,  do it this way.
        windowQuit(); // first run normal dismissal code for the df we are on...
        if (trackingInfo) {
            var sep = Common.getSeparatorForUrl(webUrl);
            webUrl = webUrl + sep + 'LD=' + encodeURIComponent(trackingInfo);
        }
        if (Common.isIOS()) {
            PlayerWrapper.playDataform(Number(dfid), ns, null, true, webUrl);
        }
        else {
            PlayerWrapper.playDataform(Number(dfid), ns);
        }
    }
    else
        theAppIFace.viewDataform(dfid, ns, isSecure, urlToShowAfter, webUrl, trackingInfo);
}
// viewPeerMessage:  probably not called externally, but listed just in case it is needed.
function viewPeerMessage(dfid, ns, requiresTimeout, webUrl, trackingInfo) {
    Common.addDebugStr("ExternalContract:viewPeerMessag" + dfid + " weburl=" + webUrl);
    theAppIFace.viewPeerMessage(dfid, ns, requiresTimeout, webUrl, trackingInfo);
}
// called by thick-bits
function didResumeFromBackground() {
    Common.didResumeFromBackground();
}
// called by thick-bits
function willEnterBackground() {
    Common.willEnterBackground();
}
/* play() called by thick-bits */
function play(dataformId, webUrl, requiresTimeout, requiresEncryption, requiresX, ns, playerInMobileWebBrowser) {
    Common.addDebugStr("ExternalContract:play " + dataformId + " weburl=" + webUrl);
    if (typeof playerInMobileWebBrowser === 'undefined')
        playerInMobileWebBrowser = false;
    return window.player.playImpl(dataformId, webUrl, requiresTimeout, requiresEncryption, requiresX, ns, playerInMobileWebBrowser);
}
/* windowQuit might be called by thick bits */
function windowQuit() {
    if (window.player)
        window.player.windowQuitImpl();
}
// QSCL, running in any environment, needs access to "playerAlert".  It used
// to be defined globally in "player.js", must restore until there's a
// virtual way for QSCL to call it.
function playerAlert(msg) {
    if (typeof (BrowserPlayer) != 'undefined')
        BrowserPlayer.playerAlert(msg);
    else if (typeof (PlayerWrapper) != 'undefined')
        PlayerWrapper.toast(msg);
}
function indirecteval(s) {
    return eval(s);
}
function getSubmitXml() {
    return null;
}
function getBookmarkXML() {
    var df = Common.currentDfInPlayer();
    if (!df)
        return "";
    var stateManager = df.getStateManager();
    if (!stateManager)
        return "";
    return stateManager.bookmarkXml;
}
// override close()?
window.close = function () {
    if (typeof (PlayerWrapper) !== 'undefined' && PlayerWrapper)
        PlayerWrapper.postCommand('closeDataform');
};
// playerNext not called by thick-bits, but its called by QSCL, maybe other internal callers.
function playerNext(nextid, nextcid, nextns, nobookmark) {
    // We don't yet have an explicit interface to a 'player',
    // so have to check for existnence of different possible types.
    if (typeof BrowserPlayer !== 'undefined')
        BrowserPlayer.playerNext(nextid, nextcid, nextns, nobookmark);
    else if (typeof player !== 'undefined')
        player.playerNext(nextid, nextcid, nextns);
}
function gotFocus() {
    // should only be called by our thick bits, so ref to document OK
    q$(document.body).addClass('focused');
    FakeTextBox.updateTextBox();
}
function lostFocus() {
    // should only be called by our thick bits, so ref to document OK
    q$(document.body).removeClass('focused');
}
// videoViewTouchedOnAndroid:  called directly from Android App
// for iOS, see "PlayerWrapper.videoViewTouched" in the file of iOS_PlayerWrapper.ts
function videoViewTouchedOnAndroid(timestamp, x, y) {
    if (MobilePlayerVer.isLatest()) {
        PlayerWrapper.bringSoftControlsToFront(0.5);
        q$('screenHost').style.pointerEvents = 'auto';
    }
    else {
        player.menuPressed();
    }
}
/**
 * called from Android app (at least) when device's exit button pressed.
 */
function exitButtonPressed() {
    if (MobilePlayerVer.isLatest()) {
        if ((PageLayout.currentLayout == Arrangement.LAY_MOBILE_LANDSCAPE_2014) &&
            PageLayout.SecondPanelCnt.tabsShown() &&
            !PageLayout.IsFlatPlayer()) {
            PageLayout.ToggleSecondaryContainerSize();
            return;
        }
    }
    else if (PageLayout.GetTabsDismissable() && PageLayout.MainPanelCnt.tabsShown()) {
        var playerPanel = PanelManager.getPanelByID(PanelName.player);
        if (playerPanel) {
            PageLayout.MainPanelCnt.SelectPanel(playerPanel);
            PageLayout.MainPanelCnt.SetTabsHidden(true);
            ScreenLayout.reassertCurrentLayout();
            PageLayout.UpdateHardButtons();
            return;
        }
    }
    windowQuit();
    if (typeof (PlayerWrapper) != 'undefined') {
        PlayerWrapper.quit();
    }
}




// CommonBase.js

//xnclude "appIFace/ExternalContract.js"
/// <reference path="Window.d.ts" />
/// <reference path="mootools.d.ts" />
/// <reference path="DateUtils.ts" />
/// <reference path="Common.d.ts" />
/// <reference path="Ajax.d.ts" />
/// <reference path="ManualClickMgrClass.ts" />
/// <reference path="../js/appIFace/ExternalContract.ts" />
// perhaps should be moved to a more generic source file.
Array.isArray || (Array.isArray = function (a) {
    // is not the string '[object Array]' and
    return '' + a !== a &&
        // test with Object.prototype.toString
        {}.toString.call(a) == '[object Array]';
});
var MobilePlayerVer = (function () {
    function MobilePlayerVer() {
    }
    MobilePlayerVer.is2010 = function (ver) {
        ver = ver || Pageparams.useMobilePlayerVer;
        return (ver == MobilePlayerVer.v2010);
    };
    MobilePlayerVer.is2014 = function (ver) {
        ver = ver || Pageparams.useMobilePlayerVer;
        return (ver == MobilePlayerVer.v2014);
    };
    MobilePlayerVer.isLatest = function (ver) {
        ver = ver || Pageparams.useMobilePlayerVer;
        return (ver >= MobilePlayerVer.v2014);
    };
    MobilePlayerVer.v2010 = 2010;
    MobilePlayerVer.v2014 = 2014;
    return MobilePlayerVer;
}());
var CommonBase = (function () {
    function CommonBase() {
        this.src = "CommonWeb.ts";
        this.dpi = 0;
        this.allowOnClickInQuickClick = false;
        this.ONE_MINUTE_IN_DAYS = 1 / 24 / 60;
        this.isSecure = false;
        this.debugStrs = [];
        this.validEmailAddressRegEx = new RegExp("^([A-Za-z0-9!#$%&'*+\\/=?\\^_`{|}~\\-][A-Za-z0-9!#$%&'*+\\/=?\\^_`{|}~\\.\\-]{0,63})@([A-Za-z0-9_\\-])+\\.([A-Za-z0-9_\\.\\-])+$");
        this.quantiaUrlRegex = /^http(s)?:\/\/(.*)quantia(md|co)\.com(\/(.*))?/i;
        this.univadisUrlRegex = /^http(s)?:\/\/(.*)univadis\.com(\/(.*))?/i;
        this.protocolRegex = /^[a-z]+\:(.*)/i;
        this.isValidNumberRegex = new RegExp(/^-?[0-9]*\.?[0-9]*$/);
        this.isValidUrlRegex = RegExp('(http|https):\\/\\/(\\w+:{0,1}\\w*)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%!\\-\\/]))?', 'i');
    }
    CommonBase.prototype.appendDiv = function (container, classAttr, idval, html) {
        return this.appendElt(container, "div", classAttr, idval, html);
    };
    CommonBase.prototype.appendElt = function (container, eltTag, classAttr, idval, html) {
        var newElt = q$(document.createElement(eltTag));
        if (idval)
            newElt.id = idval;
        if (classAttr)
            newElt.className = classAttr;
        if (html)
            newElt.innerHTML = html;
        container.appendChild(newElt);
        return (newElt);
    };
    CommonBase.prototype.attemptWindowQuit = function () {
        try {
            if (typeof windowQuit !== 'undefined') {
                windowQuit();
            }
        }
        catch (e) {
            this.log('No windowQuit defined');
        }
    };
    CommonBase.prototype.calcCurrentServerTimeMs = function () {
        return this.serverDfOpenTimeMs + this.calcMsSinceDfOpen();
    };
    CommonBase.prototype.calcMsSinceDfOpen = function () {
        if (Common.clientDfOpenTimeMs != 0)
            return (new Date()).getDate() - Common.clientDfOpenTimeMs;
        return 0;
    };
    /**
     * Take any number of strings (possibly null or empty)
     * and a final separator string (which may be more than one character)
     * and produce a single string skipping any null or empty args
     *
     * e.g. used for title, institution where either title or institution may be null or empty
     *
     * static concat("a", "b", null, "c", ", ") produces "a, b, c"
     */
    CommonBase.prototype.concat = function () {
        var indexOfLastArg = arguments.length - 1;
        var separator = arguments[indexOfLastArg];
        var result = "";
        var s = ""; // leftmost piece starts with no (i.e. empty) separator
        for (var i = 0; i < indexOfLastArg; ++i) {
            var aa = arguments[i];
            if (aa) {
                result = result + s + aa;
                s = separator; // subsequent pieces use the real separator
            }
        }
        return result;
    };
    CommonBase.prototype.doNothing = function () {
    };
    CommonBase.prototype.stopPropagation = function (e) {
        if (e) {
            // if (e.cancelable) {
            //     e.preventDefault();
            // }
            e.stopPropagation();
        }
    };
    CommonBase.prototype.preventDefault = function (e) {
        if (e) {
            if (e.cancelable) {
                e.preventDefault();
            }
        }
    };
    CommonBase.prototype.encodeToHTML = function (s) {
        s = s + "";
        s = s.replace(/&/g, '&amp;');
        s = s.replace(/</g, '&lt;');
        s = s.replace(/>/g, '&gt;');
        s = s.trim().replace(/\n/g, '<br>');
        return s;
    };
    CommonBase.prototype.encodeToHTMLRespectingNewLinesAndSpaces = function (s) {
        s = s + "";
        s = s.replace(/&/g, '&amp;');
        s = s.replace(/</g, '&lt;');
        s = s.replace(/>/g, '&gt;');
        s = makeHtmlRespectingNewlinesAndSpaces(s);
        return s;
    };
    CommonBase.prototype.encodeFromHTML = function (s) {
        s = s + "";
        s = s.replace(/&amp;/g, '&');
        s = s.replace(/&lt;/g, '<');
        s = s.replace(/&gt;/g, '>');
        s = s.trim().replace(/<br>/g, '\n');
        return s;
    };
    CommonBase.prototype.executeDfButtonAction = function (id) {
        // nop -- see overrides
    };
    CommonBase.prototype.fadeToOpacity = function (element, opacity, effectDuration, onCompleteCallback) {
        var fx = new Fx.Tween(element, {
            property: 'opacity',
            wait: false,
            duration: effectDuration,
            transition: Fx.Transitions.Sine.easeInOut,
            onComplete: (onCompleteCallback) ? onCompleteCallback : Common.doNothing
        });
        fx.start(opacity);
    };
    CommonBase.prototype.getCid = function () {
        var cid = queryString('cid');
        if (!cid) {
            cid = null; // null or empty string
        }
        return cid;
    };
    CommonBase.prototype.getDPI = function () {
        if (!this.dpi) {
            var widget = q$(document.createElement('div'));
            widget.id = 'dpiWidget';
            widget.style.width = '1in';
            widget.style.position = 'absolute';
            widget.style.left = "-1000px";
            widget.style.top = "-1000px";
            document.body.appendChild(widget);
            this.dpi = Number(widget.getSize().x);
            widget.style.display = 'none';
        }
        return this.dpi;
    };
    CommonBase.prototype.genericCompare = function (whichSort, direction, a, b) {
        var aStr = "" + a[whichSort];
        var bStr = "" + b[whichSort];
        if (aStr.match(/^\d+$/) && bStr.match(/^\d+$/))
            return direction * (Number(bStr) - Number(aStr));
        var minLen = Math.min(aStr.length, bStr.length);
        for (var i = 0; i < minLen; ++i) {
            if (bStr.charAt(i) > aStr.charAt(i))
                return direction;
            if (aStr.charAt(i) > bStr.charAt(i))
                return -direction;
        }
        return direction * (bStr.length - aStr.length);
    };
    /**
     * On mobile, returns PlayerWrapper if called from a player,
     * otherwise HomeBrowser.
     * On web, returns null
     * TODO: when we have a common thick bits API, make the return
     * type of getThickAppInterface return that interface
     */
    CommonBase.prototype.getThickAppInterface = function () {
        if (typeof HomeBrowser != 'undefined')
            return HomeBrowser;
        else
            return null;
    };
    CommonBase.prototype.handleLogout = function () {
        gQCredentials.AttemptLogout();
        gQCredentials.DeleteCachedCredentials();
        createCookie("com.quantia.wc.volume", '50', -1);
        Common.viewInternalPage("/home", "Logout");
        return false;
    };
    CommonBase.prototype.ischidden = function (item) {
        if (!item)
            return false;
        if (Array.isArray(item))
            return false;
        var elem = q$(item);
        if (!elem)
            return false;
        return elem.hasClass('cHidden');
    };
    CommonBase.prototype.chide = function (item) {
        if (!item)
            return;
        if (Array.isArray(item)) {
            // if item is an array, recurse on each subitem
            for (var i = 0; i < item.length; i++) {
                Common.chide(item[i]);
            }
        }
        else {
            // else just act on the item
            var elem = q$(item);
            if (elem)
                elem.addClass('cHidden');
        }
    };
    CommonBase.prototype.cshow = function (item) {
        if (!item)
            return;
        if (Array.isArray(item)) {
            // if item is an array, recurse on each subitem
            for (var i = 0; i < item.length; i++) {
                Common.cshow(item[i]);
            }
        }
        else {
            var elem = q$(item);
            if (elem)
                elem.removeClass('cHidden');
        }
    };
    CommonBase.prototype.cShowOrHide = function (item, bShow) {
        if (bShow)
            Common.cshow(item);
        else
            Common.chide(item);
    };
    CommonBase.prototype.fadeIn = function (item) {
        var e = q$(item);
        if (e)
            e.removeClass('cHidden');
    };
    CommonBase.prototype.showMsgAndAutoClose = function (boxid, textid, textval) {
        var elt = q$(boxid);
        var msDuration = 3000;
        var msFade = 250;
        Common.fadeToOpacity(elt, 0, 1, function () {
            Common.cshow(elt);
            q$(textid).innerHTML = textval;
            Common.fadeToOpacity(elt, 1, msFade, function () {
                setTimeout(function () {
                    Common.fadeToOpacity(elt, 0, msFade, function () {
                        Common.chide(elt);
                    });
                }, msDuration);
            });
        });
    };
    CommonBase.prototype.hideChildren = function (item) {
        q$(item).getChildren().each(function (e) {
            e.addClass('cHidden');
        });
    };
    CommonBase.prototype.hoverHelper = function (obj, callback) {
        // must implement
    };
    /**
     * Relative urls or full URLs to quantiamd, quantiaco, univadis are internal
     * All other urls are external
     * @param url a string to check
     * @returns {boolean} true if the argument refers to an url that will be serviced by QMD
     */
    CommonBase.prototype.isExternalUrl = function (url) {
        if (url.match(Common.quantiaUrlRegex))
            return false;
        if (url.match(Common.univadisUrlRegex))
            return false;
        return (url.match(Common.protocolRegex) !== null);
    };
    CommonBase.prototype.isMobilePlayer = function () {
        // should be overridden where appropriate
        return false;
    };
    CommonBase.prototype.isWeb = function () {
        return false;
    };
    CommonBase.prototype.isIOS = function () {
        var lcDeviceClass = Pageparams.deviceClass ? Pageparams.deviceClass.toLowerCase() : '';
        return (lcDeviceClass.indexOf('iphone') >= 0 || lcDeviceClass.indexOf('ipad') >= 0);
    };
    CommonBase.prototype.isIPhone = function () {
        var lcDeviceClass = Pageparams.deviceClass ? Pageparams.deviceClass.toLowerCase() : '';
        return (lcDeviceClass.indexOf('iphone') >= 0);
    };
    CommonBase.prototype.isIPad = function () {
        var lcDeviceClass = Pageparams.deviceClass ? Pageparams.deviceClass.toLowerCase() : '';
        return (lcDeviceClass.indexOf('ipad') >= 0);
    };
    CommonBase.prototype.isAndroid = function () {
        var lcDeviceClass = Pageparams.deviceClass ? Pageparams.deviceClass.toLowerCase() : '';
        return (lcDeviceClass.indexOf('android') >= 0);
    };
    CommonBase.prototype.jsonParse = function (src) {
        var parsed = null;
        try {
            if (Browser.name == 'ie' && Browser.version < 8) {
                // older IE's don't support JSON.parse natively
                // the following is from code.google.com/p/json-sans-eval
                // it's browser independent, fast and secure (no eval)
                parsed = window.jsonParse(src);
            }
            else {
                parsed = JSON.parse(src);
            }
        }
        catch (e) {
            Common.addDebugStr("jsonParse error");
            Common.addDebugStr(src);
            throw e;
        }
        return parsed;
    };
    CommonBase.prototype.LD = function (linkDescription) {
        // drop the cookie for 4 seconds
        createCookie("LD", linkDescription, 0.00004);
    };
    CommonBase.prototype.log = function (msg) {
        if (typeof console !== 'undefined') {
            console.log(msg);
        }
    };
    CommonBase.prototype.newEltOfClass = function (eltTag, classAttr, idval, html) {
        var newElt = q$(document.createElement(eltTag));
        if (classAttr)
            newElt.addClass(classAttr);
        if (idval)
            newElt.id = idval;
        if (html)
            newElt.innerHTML = html;
        return (newElt);
    };
    CommonBase.prototype.openForgotPassword = function (emailVal) {
        emailVal = emailVal || '';
        var elem = q$('forgotPasswordStatus');
        elem.innerHTML = '';
        elem.addClass('cHidden');
        elem = q$('invalidEmail');
        elem.innerHTML = '';
        elem.addClass('cHidden');
        q$('emailEntryArea').removeClass('cHidden');
        q$('forgotPasswordEmail').value = '';
        var forgotPasswordDialog = new QModalDialog(q$('requestPasswordReset'), QSTR.resetPassword);
        forgotPasswordDialog.setHeight("260px");
        forgotPasswordDialog.show(null);
        return false;
    };
    CommonBase.prototype.getCreatePwdEmailCookieIfValid = function () {
        // both cookies have to be present for email to be valid.
        // email cookie expires short period after registration (1 day).
        // token cookie is session based, will expire if browser closed.
        var token = readCookie("createpwdtoken");
        var emailAddr = readCookie("createpwdemail");
        if (emailAddr) {
            // strip off quotes if they happen to appear (observed in scenario, but not sure why)
            emailAddr = emailAddr.replace('"', '');
            emailAddr = emailAddr.replace('"', '');
        }
        if (!token || !emailAddr) {
            return null;
        }
        return emailAddr;
    };
    CommonBase.prototype.openResetPassword = function (allowCloseButton) {
        var emailAddrFromCreatePwdCookie = this.getCreatePwdEmailCookieIfValid();
        if (!emailAddrFromCreatePwdCookie) {
            // revert to openForgotPassword if createpwd coookie (created during
            // one-click registration) is not available.
            Common.openForgotPassword();
            return;
        }
        var elem = q$('forgotPasswordStatus');
        elem.innerHTML = '';
        Common.chide(elem);
        elem = q$('invalidEmail');
        elem.innerHTML = '';
        Common.chide(elem);
        Common.cshow(q$('emailEntryArea'));
        q$('modalPwdResetDlgEmail').value = emailAddrFromCreatePwdCookie;
        q$('modalPwdResetDlgPassword').value = '';
        q$('modalPwdResetDlgConfirmPassword').value = '';
        var dlg = new QModalDialog(q$('modalPwdResetDlg'), QSTR.resetPassword);
        dlg.setHeight("260px");
        dlg.updateHideClose(!allowCloseButton);
        dlg.show(null);
        q$('modalPwdResetDlgPassword').focus();
        return false;
    };
    // IE9,10 send beforeunload events when they shouldn't... suppress
    // per bug 425
    CommonBase.prototype.openWindow = function (href, title, options) {
        // SHOULD override
    };
    CommonBase.prototype.openTermsOfUse = function () {
        this.openPopup("/popups/QMD/termsOfUse.html");
        return false;
    };
    CommonBase.prototype.openPopup = function (url) {
        // SHOULD override
        var urlId = url.substring(0, url.lastIndexOf('.'));
        while (urlId.indexOf("/") !== -1) {
            urlId = urlId.replace("/", "_");
        }
        window.open(url, urlId, "width=560,height=600,status=no,location=yes,menubar=no,scrollbars=yes,resizable=no");
    };
    CommonBase.prototype.postQuestion = function (chid, keywords) {
        var arg = "";
        this.addDataLayerClickEvent('askQuestion');
        if (PageFlavor.isFromApp()) {
            var obj = { channelId: chid };
            if (keywords) {
                obj.keywords = keywords;
            }
            HomeBrowser.sendPanelMessage("home", "composePublic", JSON.encode(obj), true);
        }
        else if (PageFlavor.isMoBr()) {
            if (chid)
                arg = "?chid=" + chid;
            // NB: mobile browser only URL
            document.location.href = "/compose_public.jsp" + arg;
        }
        else {
            if (chid)
                arg = "?chid=" + chid;
            // NB: desktop only URL
            document.location.href = "/newPublicDiscussion" + arg;
        }
    };
    CommonBase.prototype.quickReload = function () {
        // SHOULD override
    };
    CommonBase.prototype.returnFalse = function () {
        return false;
    };
    CommonBase.prototype.returnTrue = function () {
        return true;
    };
    CommonBase.prototype.scrollToHeight = function (element, height, effectDuration, onCompleteCallback) {
        var fx = new Fx.Tween(element, {
            property: 'height',
            wait: false,
            duration: effectDuration,
            transition: Fx.Transitions.Sine.easeInOut,
            onComplete: onCompleteCallback
        });
        fx.start(height);
    };
    CommonBase.prototype.searchMouseExit = function (e) {
        var t = e.target;
        t.removeClass('invert');
    };
    CommonBase.prototype.searchMouseMove = function (e) {
        var cx = e.client.x;
        var t = e.target;
        var coords = t.getCoordinates();
        var offsetFromRight = coords.right - cx;
        if (offsetFromRight < 30) {
            t.addClass('invert');
        }
        else {
            t.removeClass('invert');
        }
    };
    CommonBase.prototype.searchMouseUp = function (e) {
        var cx = e.client.x;
        var t = e.target;
        var coords = t.getCoordinates();
        var offsetFromRight = coords.right - cx;
        if (offsetFromRight < 30) {
            Common.submitSearch();
        }
    };
    CommonBase.prototype.searchRequest = function (e) {
        var keynum = e.code;
        if (keynum == 13) {
            Common.submitSearch();
        }
    };
    CommonBase.prototype.setFollowing = function (dfg, following, callback) {
        Ajax.getText("/q-webclient/?cmd=setfollowing&dfg=" + dfg + "&following=" + following + "&cb=" + DateUtils.msNow(), callback);
    };
    CommonBase.prototype.submitForgotPassword = function () {
        var email = q$('forgotPasswordEmail').value;
        if (email == '')
            return;
        var pstatus = q$('invalidEmail');
        var ematch = email.match(Common.validEmailAddressRegEx);
        if (ematch == null) {
            pstatus.innerHTML = "<div class='error'>" + QSTR.enterValidEmailAddress + "</div>";
            Common.cshow(pstatus);
            return;
        }
        var updateStatus = function () {
            var statusElt = q$('forgotPasswordStatus');
            statusElt.className = "statusOK";
            statusElt.innerHTML =
                sprintf(QSTR.forgotPasswordSuccess, q$('forgotPasswordEmail').value);
            Common.chide('emailEntryArea');
        };
        setTimeout(function () {
            var addr = q$('forgotPasswordEmail').value;
            var url = "/q-webclient/?cmd=sendpass&email=" + encodeURIComponent(addr);
            Ajax.post(url, "", "text/plain", updateStatus, updateStatus);
        }, 200);
    };
    CommonBase.prototype.submitSearch = function () {
        var sr = q$('qSearchRequest');
        if (!sr)
            return;
        var value = sr.value;
        if ((value !== QSTR.search) && (value.trim() !== '') && (value !== QSTR.headerSearchBox)) {
            var sstring = encodeURIComponent(value);
            sstring = sstring.replace(' ', '+');
            var nexturl = QSettings.getSearchUrl() + "#s=" + sstring;
            Common.viewInternalPage(nexturl, 'search', 'Search');
        }
    };
    CommonBase.prototype.switchLanguage = function (newLanguage, close) {
        if (close) {
            var langSel = q$('languageSelector');
            Common.scrollToHeight(langSel, 0, 500, null);
            createCookie("lang", newLanguage);
            createCookie("languageConfirmed", "true");
            return;
        }
        createCookie("lang", newLanguage);
        Common.quickReload();
    };
    CommonBase.prototype.trackUrl = function (target, dfid) {
        var srcloc = location.href;
        var xmlDoc = XML.CreateDocument("<track_url></track_url>");
        var qMsgElem = xmlDoc.documentElement;
        qMsgElem.setAttribute("target", target);
        qMsgElem.setAttribute("source", srcloc);
        if (dfid)
            qMsgElem.setAttribute("dfid", dfid);
        Ajax.queueXmlToServer(QSettings.postUrl(), xmlDoc);
    };
    CommonBase.prototype.viewAbsoluteUrl = function (url, userTrackingInfo) {
        Common.LD(userTrackingInfo);
        Pageparams.nextUrl = url;
        location.href = url;
    };
    CommonBase.prototype.viewInternalPage = function (url, userTrackingInfo, exitCondition) {
        // Set "User Choice" as exitCondition is no param provived.
        Pageparams.exitCondition = (exitCondition !== undefined) ? exitCondition : "User Choice";
        Common.LD(userTrackingInfo);
        Pageparams.nextUrl = url;
        location.href = url;
    };
    CommonBase.prototype.viewInternalPageWithGA = function (url, userTrackingInfo, exitCondition) {
        this.addDataLayerClickEvent(userTrackingInfo);
        this.viewInternalPage(url, userTrackingInfo, exitCondition);
        return false;
    };
    CommonBase.prototype.viewExternalPage = function (url, dfid, userTrackingInfo) {
        if (userTrackingInfo)
            userTrackingInfo = url + "&LD=" + encodeURIComponent(userTrackingInfo);
        else
            userTrackingInfo = url;
        if (url.indexOf(':') < 0) {
            url = 'http://' + url;
        }
        Common.trackUrl(userTrackingInfo, dfid);
        Pageparams.nextUrl = url;
        window.open(url, '_blank');
    };
    CommonBase.prototype.viewExternalPageWithoutTracking = function (url) {
        url = replaceUrlTokens(url);
        Pageparams.nextUrl = url;
        window.open(url, '_blank');
    };
    CommonBase.prototype.viewAttachment = function (url, dfid) {
        // SHOULD override when necessary.
    };
    CommonBase.prototype.validateEmailAgainstRegex = function (emailAddress) {
        var ematch = emailAddress.match(Common.validEmailAddressRegEx);
        return !(ematch === null);
    };
    CommonBase.prototype.getSeparatorForUrl = function (url) {
        return (url.indexOf('?') == -1) ? '?' : '&';
    };
    CommonBase.prototype.isRelativeUrl = function (url) {
        return (url.charAt(0) == '/');
    };
    CommonBase.prototype.xxparseURL = function (url) {
        var parser = document.createElement('a'), searchObject = {}, queries, split, i;
        // Let the browser do the work
        parser.href = url;
        // Convert query string to object
        queries = parser.search.replace(/^\?/, '').split('&');
        for (i = 0; i < queries.length; i++) {
            split = queries[i].split('=');
            searchObject[split[0]] = split[1];
        }
        return {
            protocol: parser.protocol,
            host: parser.host,
            hostname: parser.hostname,
            port: parser.port,
            pathname: parser.pathname,
            search: parser.search,
            searchObject: searchObject,
            hash: parser.hash
        };
    };
    CommonBase.prototype.screenHasVariableHeight = function (screenType) {
        if (screenType == 'QuestionResultsScreen' ||
            screenType == 'QuestionScreen' ||
            screenType == 'ActionListScreen' ||
            screenType == 'UpvoteQPointScreen') {
            return true;
        }
        return false;
    };
    CommonBase.prototype.screenIsVideo = function (screenType) {
        if (screenType == 'VideoScreen' ||
            screenType == 'FlashVideoScreen') {
            return true;
        }
        return false;
    };
    CommonBase.prototype.nsRequiresX = function (ns) {
        if (ns === 'dataform:peermessage')
            return true;
        if (ns === 'dataform:discussion')
            return true;
        return false;
    };
    CommonBase.prototype.nsRequiresEncryption = function (ns) {
        if (ns === 'dataform:peermessage')
            return true;
        if (ns === 'dataform:discussion')
            return true;
        return false;
    };
    CommonBase.prototype.getManualClickMgr = function () {
        if (!this.manualClickMgr)
            this.manualClickMgr = new ManualClickMgrClass();
        return this.manualClickMgr;
    };
    CommonBase.prototype.nextArgSep = function (url) {
        var sep = "";
        if (url.charAt(url.length - 1) == "?") {
            // nop
        }
        else if (url.indexOf("?") > -1) {
            sep = "&";
        }
        else {
            sep = "?";
        }
        return sep;
    };
    CommonBase.prototype.isValidNumber = function (s) {
        return this.isValidNumberRegex.test(s);
    };
    CommonBase.prototype.isValidUrl = function (url) {
        if (!url)
            return false;
        return this.isValidUrlRegex.test(url);
    };
    CommonBase.prototype.QSetTimeout = function (period, refname, func) {
        return setTimeout(function () {
            //if (refname && refname.substr(0,1) != "!")
            //    console.log("Timeout reached: " + refname);
            func();
        }, period);
    };
    CommonBase.prototype.getIOSversion = function () {
        if (/iP(hone|od|ad)/.test(navigator.platform)) {
            // supports iOS 2.0 and later: <http://bit.ly/TJjs1V>
            var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
            return [
                parseInt(v[1], 10),
                parseInt(v[2], 10),
                parseInt(v[3] || '0', 10)
            ];
        }
        else if (this.isIOS()) {
            // simulator in Chrome
            return [7, 1, 1];
        }
        else {
            return null;
        }
    };
    CommonBase.prototype.supportsInlineVideo = function () {
        var iOSVer = this.getIOSversion();
        if (iOSVer && !this.isIPad()) {
            // ios versons before  10 did not support inline
            var ver = this.getIOSversion();
            if (iOSVer[0] < 10)
                return false;
        }
        // all other devices do
        return true;
    };
    CommonBase.prototype.toggleGroup = function (groupId, button, refreshOnChange) {
        // SHOULD OVERRIDE
    };
    /**
     * Initializes the dataLayer object which manages the gtm events
     *  For Weband Mobile browsers, dataLayer object is wrapped with GTM fonctaionnalities that sends the events to GA servers
     *  In case of Webviews for Mobile Apps/iOs, dataLayer sends the catched events to the native container of the Application
     * @returns {Array<any>}
     */
    CommonBase.prototype.initDataLayer = function () {
        dataLayer = new Array();
        var instance = this;
        dataLayer.push = function (eventObject) {
            if (!eventObject)
                return;
            if (instance.hasMobileAppNativeContainerJsInterface()) {
                var properties = [];
                for (var prop in eventObject) {
                    properties.push(encodeURIComponent(prop) + "=" + encodeURIComponent(eventObject[prop]));
                }
                var propertiesStr = properties.join('&');
                instance.sendGAEventOverMobileAppNativeContainer(propertiesStr);
            }
            else {
                // keep the same behavior
                Array.prototype.push.call(dataLayer, eventObject);
            }
        };
        return dataLayer;
    };
    /**
     * Tells if there is a defined JavaScript interface that allows to send GTM events through the Mobile APP native container.
     * If the page is displayed over a web browser (desktop/mobile), this method should always returns false.
     * @returns {boolean} true if there is defined JS interface, false otherwise
     */
    CommonBase.prototype.hasMobileAppNativeContainerJsInterface = function () {
        // must override in CommonXMobilePlayer.ts and CommonXMobileNonPlayer.ts
        return false;
    };
    /**
     * Sends event to the application native container
     * This event is sent  in priority over  HomeBrowser.sendGAEvent if it's defined. If not, then it's sent over    PlayerWrapper.sendGAEvent if it's defined
     * @param {string} eventProperties  in form of a url query: event1=val1&event2=val2
     */
    CommonBase.prototype.sendGAEventOverMobileAppNativeContainer = function (eventProperties) {
        console.warn("Mobile App  GTM JavaScript Interface called in CommonBase.ts");
    };
    CommonBase.prototype.sendQuantiaDataLayerToGTM = function () {
        // this is included with google tool kit manager
        if (typeof sendToGTM != 'undefined') {
            sendToGTM(window, document, 'script', 'dataLayer', 'GTM-K9SH87');
        }
    };
    // MUST NOT throw
    CommonBase.prototype.addDataLayerEvent = function (evnt) {
        try {
            if (!evnt)
                return;
            if ((typeof dataLayer != 'undefined') && dataLayer != null)
                dataLayer.push(evnt);
        }
        catch (e) {
        }
    };
    // MUST NOT throw
    CommonBase.prototype.addDataLayerClickEvent = function (evntName) {
        if (!evntName)
            return;
        Common.addDataLayerEvent({ 'event': evntName });
    };
    // addDebugStr -- adds a string to debugStrs array, which can be inspected
    // later via JS debugger console.  Useful for debugging mobile startup scenarios
    // where code runs BEFORE a debugger can be attached.
    CommonBase.prototype.addDebugStr = function (s) {
        // don't let array grow without bound.
        if (this.debugStrs.length > 100)
            this.debugStrs.shift();
        this.debugStrs.push(s);
        console.log(s);
    };
    CommonBase.prototype.createAuthorNameRegion = function (df, author, isUserObserver) {
        var authorNameRegion = '<div class="authorNameRegion">';
        var buttonClassName = "button";
        var buttonUIStr = QSTR.messageLabel;
        if (author.getPrefix())
            authorNameRegion += '<div class="authorPrefix">' + author.getPrefix() + '</div>';
        authorNameRegion += '<div class="authorName">' + author.GetName() + '</div>';
        //      if (language === 'ja') {
        if (Common.returnFalse()) {
            if (author.getTitle())
                authorNameRegion += '<div class="authorTitle">' + author.getTitle() + '</div>';
            if (author.GetInstitution())
                authorNameRegion += '<div class="authorInstitution">' + author.GetInstitution() + '</div>';
        }
        else {
            if (author.getTitle()) {
                authorNameRegion += '<div class="authorTitle">' + author.getTitle();
                if (author.GetInstitution())
                    authorNameRegion += ', ';
                authorNameRegion += '</div>';
            }
            if (author.GetInstitution())
                authorNameRegion += '<div class="authorInstitution">' + author.GetInstitution() + '</div>';
        }
        if (df.canUserContactAnAuthor() && !author.getOptOutOfContact()) {
            if (MobilePlayerVer.isLatest()) {
                buttonClassName = "messageButtonInfoPanel2014";
                if (isUserObserver) {
                    buttonClassName = "cHidden";
                }
                buttonUIStr = '<div class="envelopeOnMsgButton"></div><div>' + buttonUIStr + '</div>';
            }
            var xxScreenDoor = "'" + author.GetScreenDoor() + "'";
            var xxName = "'" + author.GetName().replace(/'/g, "\\u0027") + "'";
            authorNameRegion +=
                '<div class="' + buttonClassName + '" ' +
                    'onclick="PanelHandler.bringComposeToFront(' +
                    xxScreenDoor +
                    ', ' +
                    xxName +
                    '); return false;">' +
                    buttonUIStr + '</div>\n';
        }
        authorNameRegion += '</div>';
        return (authorNameRegion);
    };
    CommonBase.prototype.createNewAuthorTag = function (df, author, isUserObserver) {
        var result = "<div class='authorWithPhoto'>";
        if (author.getPhoto()) {
            var inner = '<div class="authorPhoto clearfix" style="float:left;"><img ';
            if (author.getAuthorID())
                inner = inner + 'id="photo_' + author.getAuthorID() + '" ';
            inner = inner + 'src="' + author.getPhoto() + '" />\n';
            inner = inner + '</div>';
            result += inner;
        }
        else {
            result = '<div class="authorWithoutPhoto">';
        }
        result += Common.createAuthorNameRegion(df, author, isUserObserver);
        result += '</div>';
        return result;
    };
    CommonBase.prototype.getQPointFoil128 = function (qPoints, awarded) {
        return this.getQPointFoil(qPoints, '128', awarded);
    };
    CommonBase.prototype.getQPointFoil50 = function (qPoints, awarded) {
        return this.getQPointFoil(qPoints, '50', awarded);
    };
    CommonBase.prototype.getQPointFoil = function (qPoints, sizeDir, awarded) {
        var subPath = (awarded) ? '_gray' : '';
        var leftPad = (qPoints < 10) ? '0' : '';
        var strQPoints = leftPad + qPoints;
        var fname = 'q-points_' + strQPoints + '.png';
        var srcDir = '/images/qmd/icons/' + sizeDir + subPath + '/';
        return srcDir + fname;
    };
    CommonBase.prototype.getCmeFoil50 = function (cmeHours, awarded) {
        return this.getCmeFoil(cmeHours, '50', awarded);
    };
    CommonBase.prototype.getCmeFoil128 = function (cmeHours, awarded) {
        return this.getCmeFoil(cmeHours, '128', awarded);
    };
    CommonBase.prototype.getCmeFoil = function (cmeHours, sizeDir, awarded) {
        var subPath = (awarded) ? '_gray' : '';
        var paddedCme = '' + Math.round(100 * cmeHours);
        while (paddedCme.length < 4) {
            paddedCme = '0' + paddedCme;
        }
        var fname = 'cme_' + paddedCme + '.png';
        var srcDir = '/images/qmd/icons/' + sizeDir + subPath + '/';
        return srcDir + fname;
    };
    CommonBase.prototype.htmlFragmentToText = function (input) {
        // take a string with embedded HTML (like '<i>')
        // and return just the plain text
        //
        // make a div containing the input string.
        // then extract the text from text nodes,
        // ignoring other types of ndes
        if (!input)
            return "";
        var e = document.createElement('div');
        e.innerHTML = input;
        var plaintext = "";
        var sep = "";
        for (var i = 0; i < e.childNodes.length; i++) {
            var n = e.childNodes[i];
            if (n.nodeType == 3) {
                plaintext += (sep + n.nodeValue);
                sep = " ";
            }
        }
        return plaintext;
    };
    CommonBase.prototype.replaceTokensWithEntities = function (text) {
        if (!text)
            return "";
        var newText = text.replace(/&/g, "&amp;");
        newText = newText.replace(/</g, "&lt;");
        newText = newText.replace(/>/g, "&gt;");
        newText = newText.replace(/\n/g, "<br/>");
        newText = newText.replace(/  /g, "&nbsp; ");
        return (newText);
    };
    CommonBase.prototype.openMemberHelp = function () {
        location.href = '/home/memberhelp';
    };
    CommonBase.prototype.quitButtonPressed = function () {
        // should be overridden
        return false;
    };
    CommonBase.prototype.newsButtonPressed = function () {
        // should be overridden
        return false;
    };
    CommonBase.prototype.educationButtonPressed = function () {
        // should be overridden
        return false;
    };
    CommonBase.prototype.sleep = function (milliseconds) {
        var start = new Date().getTime();
        for (var i = 0; i < 1e7; i++) {
            if ((new Date().getTime() - start) > milliseconds) {
                break;
            }
        }
    };
    CommonBase.prototype.iPhoneEscape = function (s) {
        var exp = /\%u[0-9A-F][0-9A-F][0-9A-F][0-9A-F]/gi;
        s = encodeURIComponent(s).replace(exp, function (e) {
            return decodeURIComponent(e);
        });
        s = s.replace(/@/g, "%40");
        return s;
    };
    CommonBase.prototype.reportNecessaryContent = function (msDelay) {
        // overridden in CommonXMobilePlayer
    };
    CommonBase.prototype.didResumeFromBackground = function () {
        // see override in CommonXMobilePlayer
    };
    CommonBase.prototype.willEnterBackground = function () {
        // see override in CommonXMobilePlayer
    };
    CommonBase.prototype.removeFromParent = function (xmlElement) {
        if (xmlElement == null || xmlElement == false) {
            return;
        }
        var parent = xmlElement.parentNode;
        parent.removeChild(xmlElement);
    };
    CommonBase.prototype.getXmlDataIsland = function () {
        try {
            var strName = 'embeddedXmlData';
            if (window[strName]) {
                if (window[strName] != undefined && window[strName].length > 0) {
                    var doc = XML.CreateDocument(window[strName]);
                    window[strName] = '';
                    return doc;
                }
            }
        }
        catch (e) {
        }
        return null;
        //var xmlDoc = document.getElementById("xmlData").XMLDocument;// all("testXML").XMLDocument;
    };
    CommonBase.prototype.getXmlDataIslandWithName = function (strName) {
        var nameElt = q$(strName);
        if (nameElt) {
            var value = nameElt.innerHTML;
            value = value.replace(/^\s+/, "").replace(/&nbsp;/g, " ");
            value = value.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
            value = value.replace(/QQltQQ/g, "&lt;").replace(/QQgtQQ/g, "&gt;").replace(/QQquotQQ/g, "&quot;");
            return XML.CreateDocument(value);
        }
        return null;
        //var xmlDoc = document.getElementById("xmlData").XMLDocument;// all("testXML").XMLDocument;
    };
    CommonBase.prototype.keynumForEvent = function (e) {
        // browser-specific behaviors
        var keynum = 0;
        if (window.event) {
            // IE
            var ev = window.event;
            keynum = ev.keyCode;
        }
        else if (e.which) {
            // Netscape/Firefox/Opera
            keynum = e.which;
        }
        return keynum;
    };
    CommonBase.prototype.currentDFID = function () {
        // should be overridden in CommonWeb and CommonXMobilePlayer as appropriate.
        return 0;
    };
    CommonBase.prototype.currentDfGroup = function () {
        // should be overridden in CommonWeb and CommonXMobilePlayer as appropriate.
        return 0;
    };
    CommonBase.prototype.currentDfInPlayer = function () {
        // should be overridden in CommonWeb and CommonXMobilePlayer as appropriate.
        return null;
    };
    CommonBase.prototype.setCurrentDfInPlayer = function (df) {
        // should be overridden in CommonWeb and CommonXMobilePlayer as appropriate.
        Common.addDebugStr("unexpected call to CommonBase.setCurrentDfInPlayer");
    };
    CommonBase.prototype.discoverDFIDStr = function () {
        // should be overridden in CommonWeb and CommonXMobilePlayer as appropriate.
        return "";
    };
    CommonBase.prototype.setAutoPlayAllowed = function (reason, value) {
        // only applies to ActionListScreen in player
        // should be overridden in CommonXMobilePlayer and CommonWeb
    };
    CommonBase.prototype.actionListAdvance = function () {
        // only applies to ActionListScreen in player
        // should be overridden in CommonXMobilePlayer and CommonWeb
    };
    CommonBase.prototype.requestScroll = function (payload) {
        // should be overridden in CommonXMobileNonPlayer
    };
    CommonBase.prototype.showSecurePrompt = function () {
        // should be overridden in CommonXMobileNonPlayer
    };
    CommonBase.prototype.hideSecurePrompt = function () {
        // should be overridden in CommonXMobileNonPlayer
    };
    CommonBase.prototype.dim = function (payload) {
        // should be overridden in CommonXMobileNonPlayer
    };
    CommonBase.prototype.undim = function () {
        // should be overridden in CommonXMobileNonPlayer
    };
    CommonBase.prototype.showChannelContents = function (block) {
        var elem = document.getElementById(block.blockID);
        var btn = document.getElementById(block.buttonID);
        var lastPlusOne = 0;
        if (elem) {
            lastPlusOne = block.index + block.chunkSize;
            if (lastPlusOne >= block.divs.length) {
                lastPlusOne = block.divs.length;
                btn.className = 'cHidden';
            }
            var temp = [];
            temp[0] = '';
            for (var index = block.index; index < lastPlusOne; ++index) {
                temp[temp.length] = block.divs[index];
            }
            elem.innerHTML = elem.innerHTML + temp.join('\n');
        }
        return lastPlusOne;
    };
    CommonBase.prototype.ShowMoreContents = function (itemOnPageID) {
        // contentDivs written by FMT
        for (var index = 0; index < contentDivs.length; ++index) {
            var block = contentDivs[index];
            if (block.itemOnPageID == itemOnPageID) {
                block.index = this.showChannelContents(block);
                AfterStartupEvents.doAfterDomChange();
                return;
            }
        }
    };
    CommonBase.prototype.updateKWCmd = function (url) {
        var updateKwCmdCallback = function (responseObj, t) {
            if (!responseObj)
                return;
            if (responseObj.status === "OK") {
                // just reload the page.
                Common.quickReload();
            }
            else {
                console.error("FAILURE in updateKWCmd");
            }
        };
        Ajax.getJSON(url, updateKwCmdCallback);
        return true;
    };
    return CommonBase;
}());
/*** IPreloadRequest ***/
var IPreloadRequest = (function () {
    function IPreloadRequest(qcpUrl, isStreaming, isAudio) {
        this.qcpUrl = qcpUrl;
        this.isStreaming = isStreaming;
        this.isAudio = isAudio;
    }
    IPreloadRequest.makeStreamingAudioRequest = function (qcpUrl) {
        return new IPreloadRequest(qcpUrl, true, true);
    };
    IPreloadRequest.makeStaticRequest = function (qcpUrl) {
        return new IPreloadRequest(qcpUrl, false, false);
    };
    IPreloadRequest.makeVideoRequest = function (qcpUrl) {
        return new IPreloadRequest(qcpUrl, true, false);
    };
    return IPreloadRequest;
}());

//include "appIFace/ExternalContract.js"



// CommonWeb.js

//xnclude "AfterStartupEvents.js"
//xnclude "CommonBase.js"
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
/// <reference path="Window.d.ts" />
/// <reference path="mootools.d.ts" />
/// <reference path="DateUtils.ts" />
/// <reference path="Common.d.ts" />
/// <reference path="Ajax.d.ts" />
/// <reference path="CommonBase.ts" />
/// <reference path="QCredentials.ts" />
/// <reference path="QUtils.ts" />
/// <reference path="MemoryManagement.ts" />
/* for IE7 or any other very old browser that doesn't support console.log */
if (typeof console === 'undefined') {
    // faux console
    window.console = {
        assert: function (test, message) {
            var optionalParams = [];
            for (var _i = 2; _i < arguments.length; _i++) {
                optionalParams[_i - 2] = arguments[_i];
            }
        },
        clear: function () { },
        count: function (countTitle) { },
        debug: function (message) {
            var optionalParams = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                optionalParams[_i - 1] = arguments[_i];
            }
        },
        dir: function (value) {
            var optionalParams = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                optionalParams[_i - 1] = arguments[_i];
            }
        },
        dirxml: function (value) { },
        error: function (message) {
            var optionalParams = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                optionalParams[_i - 1] = arguments[_i];
            }
        },
        group: function (groupTitle) { },
        groupCollapsed: function (groupTitle) { },
        groupEnd: function () { },
        info: function (message) {
            var optionalParams = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                optionalParams[_i - 1] = arguments[_i];
            }
        },
        msIsIndependentlyComposed: function (element) { return false; },
        log: function (message) {
            var optionalParams = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                optionalParams[_i - 1] = arguments[_i];
            }
        },
        profile: function (reportName) { },
        profileEnd: function () { },
        select: function (element) { },
        time: function (timerName) { },
        timeEnd: function (timerName) { },
        trace: function () { },
        warn: function (message) {
            var optionalParams = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                optionalParams[_i - 1] = arguments[_i];
            }
        }
    };
}
function $$$(e) {
    if (!$$$["_vals"])
        $$$["_vals"] = {};
    var result = q$(e);
    if (result === null) {
        if ($$$["_vals"][e] === undefined) {
            $$$["_vals"][e] = {};
        }
        result = $$$["_vals"][e];
    }
    return result;
}
var CommonWeb = (function (_super) {
    __extends(CommonWeb, _super);
    function CommonWeb() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.src = "CommonWeb.ts";
        _this._currentDfInPlayer = null;
        return _this;
    }
    // faster than location.reload(true) because it doesn't reload js and css as well
    // useful for reloading after login, etc
    CommonWeb.prototype.quickReload = function () {
        Common.getManualClickMgr().init(); // need to reset
        this.attemptWindowQuit();
        var thisUrl = document.location.href;
        var poundIndex = thisUrl.indexOf("#");
        var inboxIndex = thisUrl.indexOf('inbox');
        if (poundIndex > 0) {
            if (inboxIndex > -1) {
                var hash = thisUrl.substring(poundIndex + 1);
                createCookie('dftoshow', hash);
            }
            thisUrl = thisUrl.substring(0, poundIndex);
        }
        document.location.href = thisUrl;
    };
    CommonWeb.prototype.updateAfterToggleGroup = function (parent, isFollowing, refreshOnChange) {
        if (refreshOnChange) {
            window.location.reload();
            return;
        }
        // else update the elements directly
        var childElt = parent.firstElementChild;
        if (!isFollowing) {
            childElt.addClass('isFollowing');
            $$('.followLabel')[0].innerHTML = q$('groupLeaveText').value;
            Common.cshow('memberHtml');
            Common.chide('nonMemberHtml');
            var okButton = q$('okButton');
            if (okButton) {
                Common.chide('join');
                Common.cshow('leave');
            }
            else {
                var canLeaveGroup = q$('canLeaveGroup');
                if (!canLeaveGroup) {
                    Common.chide('groupOptInButtonContainer');
                }
            }
        }
        else {
            childElt.removeClass('isFollowing');
            $$('.followLabel')[0].innerHTML = q$('groupJoinText').value;
            Common.chide('memberHtml');
            Common.cshow('nonMemberHtml');
            var okButton = q$('okButton');
            if (okButton) {
                Common.cshow('join');
                Common.chide('leave');
            }
        }
    };
    // called from FMT
    CommonWeb.prototype.toggleGroup = function (groupId, button, refreshOnChange) {
        var parent = q$(button).getParent(".membershipCheckBox");
        var childElt = parent.firstElementChild;
        var isFollowing = childElt.hasClass('isFollowing');
        setTimeout(function () {
            var url = "/q-webclient/?cmd=joingroup&join=" + !isFollowing + "&gr=" + groupId;
            Ajax.getText(url, function () {
                this.updateAfterToggleGroup(parent, isFollowing, refreshOnChange);
            });
        }, 500);
    };
    CommonWeb.prototype.openWindow = function (href, title, options) {
        window.open(href, title, options);
    };
    CommonWeb.prototype.openPopup = function (url) {
        var urlId = url.substring(0, url.lastIndexOf('.'));
        while (urlId.indexOf("/") !== -1) {
            urlId = urlId.replace("/", "_");
        }
        window.open(url, urlId, "width=560,height=600,status=no,location=yes,menubar=no,scrollbars=yes,resizable=no");
    };
    CommonWeb.prototype.hoverHelper = function (obj, callback) {
        obj.callback = callback;
        obj.onmouseover = function () {
            obj.hover = true;
            obj.callback();
        };
        obj.onmouseout = function () {
            obj.hover = false;
            obj.mousedown = false;
            obj.callback();
        };
        obj.onmousedown = function () {
            obj.mousedown = true;
            obj.callback();
        };
        obj.onmouseup = function () {
            obj.mousedown = false;
            obj.callback();
        };
        MemoryManagement.HoverItemsAdd(obj);
        callback();
    };
    CommonWeb.prototype.isWeb = function () {
        return true;
    };
    CommonWeb.prototype.executeDfButtonAction = function (id) {
        try {
            var df = Common.currentDfInPlayer();
            if (!df)
                return;
            var actionList = df.getActionList();
            if (actionList) {
                var action = actionList[id];
                if (action) {
                    action.AndroidOnClick();
                }
            }
        }
        catch (e) {
        }
    };
    CommonWeb.prototype.setAutoPlayAllowed = function (reason, value) {
        // only applies to ActionListScreen in player
        if (typeof (ActionListScreenForDesktop) !== 'undefined')
            ActionListScreenForDesktop.SetAutoPlayAllowed(reason, value);
    };
    CommonWeb.prototype.actionListAdvance = function () {
        // only applies to ActionListScreen in player
        Common.addDataLayerClickEvent('nextPresentationDFPlayer');
        if (typeof (ActionListScreenForDesktop) !== 'undefined')
            ActionListScreenForDesktop.advance();
    };
    CommonWeb.prototype.currentDFID = function () {
        if (this._currentDfInPlayer)
            return this._currentDfInPlayer.getDataformID();
        else
            return 0;
    };
    CommonWeb.prototype.currentDfGroup = function () {
        if (this._currentDfInPlayer)
            return this._currentDfInPlayer.getDataformGroupID();
        else
            return 0;
    };
    CommonWeb.prototype.currentDfInPlayer = function () {
        return this._currentDfInPlayer;
    };
    CommonWeb.prototype.setCurrentDfInPlayer = function (df) {
        this._currentDfInPlayer = df;
    };
    CommonWeb.prototype.discoverDFIDStr = function () {
        if (Pageparams.pageDataformId > 0)
            return Pageparams.pageDataformId.toString();
        var parsedUrl = Common.xxparseURL(window.location.href);
        var dfStr = parsedUrl.searchObject["df"];
        if (dfStr && dfStr.length > 0)
            return dfStr;
        var lastSlashOffset = parsedUrl.pathname.lastIndexOf("/") + 1;
        if (lastSlashOffset <= 0)
            return '';
        var lastTokenText = parsedUrl.pathname.substring(lastSlashOffset);
        dfStr = '';
        if (lastTokenText) {
            if (Number(lastTokenText) > 0)
                dfStr = lastTokenText;
            else
                dfStr = ScreenDoor.From(lastTokenText).toString();
        }
        return dfStr;
    };
    return CommonWeb;
}(CommonBase));
window.Common = new CommonWeb();
////////////////////PAGE HEADER SECTION///////////////////////
// For "Web" cases, initiate the "afterStartup"  through 'domready'
// (a mootools event for DOMContentLoaded for modern browsers)
window.addEvent('domready', AfterStartupEvents.doAfterStartup.bind(AfterStartupEvents));
doOnPageReady(function () {
    gQCredentials.updateCookiesAtStartup();
    return true;
});

//include "AfterStartupEvents.js"
//include "CommonBase.js"



// ManualClickMgrClass.js

/// <reference path="Common.d.ts" />
/// <reference path="SoftPlayerControls.ts" />
/**
 * ManualClickMgrClass manages state of a manual click required
 * by IOS before our script can cause html5 audio/video to be played.
 */
var ManualClickMgrClass = (function () {
    function ManualClickMgrClass() {
        this.deviceRequiresClick = false;
        this.alreadyStarted = false;
        this.init();
    }
    ManualClickMgrClass.prototype.init = function () {
        // for HTML5 media in mobile web browsers, never set it back to false after setting it to true
        this.deviceRequiresClick = PageFlavor.isMoBr();
        this.alreadyStarted = false;
    };
    ManualClickMgrClass.prototype.needsClick = function () {
        return (this.deviceRequiresClick && !this.alreadyStarted);
    };
    ManualClickMgrClass.prototype.setStarted = function () {
        var hadAlreadyStarted = this.alreadyStarted;
        this.alreadyStarted = true;
        if (!hadAlreadyStarted) {
            SoftPlayerControls.setHidden(true);
        }
        var starterElts = ManualClickMgrClass.allStarterElts;
        for (var i = 0; i < starterElts.length; i++) {
            Common.chide(starterElts[i]);
        }
    };
    ManualClickMgrClass.prototype.showVersionedStarterElts = function (listener) {
        var starterElt = this.getVersionedStarterElt();
        if (!listener)
            listener = this.defaultStarterClickHandler.bind(this);
        if (starterElt) {
            Common.cshow(starterElt);
            starterElt.removeClass('vHidden');
            if (listener)
                starterElt.addListener(ManualClickMgrClass.startEvent, listener);
        }
        this.showMediaStarterSPlayer(listener);
        return starterElt;
    };
    ManualClickMgrClass.prototype.defaultStarterClickHandler = function () {
        Common.getManualClickMgr().setStarted();
        IAudioControls.PlayFirst();
        if (MobilePlayerVer.is2010())
            IAudioControls.ForceShowPause();
    };
    ManualClickMgrClass.prototype.getVersionedStarterElt = function () {
        return (MobilePlayerVer.isLatest()) ?
            q$('html5MediaPlayStarter') :
            q$('playStarter2010');
    };
    ManualClickMgrClass.prototype.showCoverWithPlayStarter = function () {
        var elt = q$('coverWithPlayStarter');
        if (elt)
            elt.removeClass('cHidden');
        return elt;
    };
    ManualClickMgrClass.prototype.showMediaStarterSPlayer = function (listener) {
        var elt = q$('mediaStarterSPlayer');
        if (elt) {
            Common.cshow(elt);
            if (listener)
                elt.addEventListener('touchstart', listener);
        }
        return elt;
    };
    ManualClickMgrClass.prototype.showCoverPlusStarterMobileWeb = function (listener) {
        var elt = q$('coverPlusPlayStarterMobileWeb');
        if (elt) {
            Common.cshow(elt);
            if (listener)
                elt.addEventListener('touchstart', listener);
        }
        return elt;
    };
    ManualClickMgrClass.allStarterElts = ['coverWithPlayStarter', 'html5MediaPlayStarter', 'coverPlusPlayStarterMobileWeb', 'mediaStarterSPlayer', 'playStarter2010'];
    ManualClickMgrClass.startEvent = "click";
    return ManualClickMgrClass;
}());
doOnPageReady(function () {
    Common.getManualClickMgr().init();
    return false;
});




// QSettingsOne.js

/// <reference path="IQSettings.d.ts" />
/// <reference path="QAuthCookie.ts" />
/// <reference path="DateUtils.ts" />
/// <reference path="mootools.d.ts" />
/// <reference path="QUtils.ts" />
/// <reference path="ScreenDoor.ts" />
var QSettingsOne = (function () {
    function QSettingsOne() {
        this._protocol = "";
        this._domainFull = "";
        this._nonSecureDomain = "";
        this._secureDomain = "";
        this._contentDomain = "";
        this.BustCache = false;
        this.CleanedUserAgent = "";
        this.Version = "";
        this.Application = "";
        this._useAbsoluteUrl = false;
        this._isDesktopBrowser = false;
        if (Common.isWeb())
            this.constructWeb();
        else
            this.constructMobile();
    }
    QSettingsOne.prototype.constructWeb = function () {
        this._isDesktopBrowser = true;
        this._useAbsoluteUrl = true;
        this._protocol = QSettingsOne.parseProtocolFromPageUrl();
        this._domainFull = this.parseDomain();
        this._nonSecureDomain = QSettingsOne.makeNonSecureDomain(this._domainFull);
        this._secureDomain = this._domainFull;
        this._contentDomain = this._domainFull;
        this.BustCache = false;
        this.CleanedUserAgent = unescape(navigator.userAgent).replace(/ /g, '/');
        this.Version = Pageparams.serverVersionV;
        // QSettingsInit may be be supplied in JS variable in header; not
        // sure why the fmt can't just call this constructor with the object as
        // a parameter.  Maybe a later TODO.
        var ini = null;
        if (typeof window.QSettingsInit != "undefined" && window.QSettingsInit)
            ini = window.QSettingsInit;
        if (this._protocol !== "https") {
            if (this._secureDomain.indexOf(".com") > -1 || this._secureDomain.indexOf(".jp") > -1) {
                this._secureDomain = this._secureDomain.replace(/www\./, "").replace(/my\./, "");
            }
        }
        if (this._contentDomain.indexOf("quantiamd.com") >= 0) {
            this._contentDomain = "myqcp.quantiamd.com";
        }
        if (!ini) {
            // why?
            if (this._contentDomain === this._domainFull) {
                this._contentDomain = this._secureDomain;
            }
        }
    };
    QSettingsOne.prototype.constructMobile = function () {
        this._isDesktopBrowser = false;
        this._useAbsoluteUrl = false;
        this.Application = "WebClient";
        this.Version = Pageparams.serverVersionV;
        this._protocol = 'http://';
        this.BustCache = false;
        // QSettingsInit may be be supplied in JS variable in header; not
        // sure why the fmt can't just call this contructur with the object as
        // a parameter.  Maybe a later TODO.
        var ini = null;
        if (typeof window.QSettingsInit != "undefined" && window.QSettingsInit)
            ini = window.QSettingsInit;
        this.initBustCache();
        // We may not be able to get these via Settings in a player context
        // so admit we don't know
        this._secureDomain = null;
        this._domainFull = null;
        this._contentDomain = null;
        // FIXME
        this.CleanedUserAgent = unescape(navigator.userAgent).replace(/ /g, '/');
    };
    // initBustCache only used in mobile?
    QSettingsOne.prototype.initBustCache = function () {
        this.BustCache = false;
        if (document.location.href.indexOf("&bc=") > 0 ||
            document.location.href.indexOf("?bc=") > 0) {
            this.BustCache = true;
        }
    };
    QSettingsOne.prototype.relOrAbs = function () {
        if (this._useAbsoluteUrl)
            return this._protocol + this._domainFull;
        else
            return "";
    };
    QSettingsOne.prototype.sslAppendix = function (isSecure) {
        if (this._isDesktopBrowser)
            return "";
        if (isSecure)
            return ";ssl";
        return "";
    };
    QSettingsOne.prototype.buildErrorUrl = function (msg) {
        var url = this.relOrAbs();
        url += "/qmd/reportProblem?p=" + encodeURIComponent(msg);
        url += "&url=" + encodeURIComponent(location.href);
        url += "&bc=" + (new Date()).getTime();
        url += this.sslAppendix(true);
        return url;
    };
    // this class uses gQCredentials and AccountInfo attributes to create URLs
    QSettingsOne.prototype.getReferralDialog = function (title, link, emailTemplate, emailBody, supportsMailTo, dfid, toEmail) {
        if (!this._isDesktopBrowser)
            throw 'getReferralDialog not implemented for mobile';
        var url = "https://" + this._secureDomain +
            "/home/referral_dialog?title=" +
            encodeURIComponent(title) + "&link=" + encodeURIComponent(link) +
            "&mt=" + supportsMailTo +
            "&emailTemplate=" + encodeURIComponent(emailTemplate) +
            "&emailBody=" + encodeURIComponent(emailBody) +
            "&dfid=" + dfid +
            "&toEmail=" + encodeURIComponent(toEmail);
        return url;
    };
    QSettingsOne.prototype.buildRootUrl = function (strUri) {
        var url = this.relOrAbs();
        url += strUri;
        return url;
    };
    QSettingsOne.prototype.buildUrlCmd = function (strCmd, cbval) {
        var url = this.relOrAbs();
        if (!cbval)
            cbval = DateUtils.msNow();
        url += "/q-webclient?cmd=" + strCmd + "&cb=" + cbval;
        return url;
    };
    // buildQcpUrlHelper just for desktop?
    QSettingsOne.prototype.buildQcpUrlHelper = function (strKey, preferredDomain) {
        var url = "";
        if (!strKey) {
            url = this.buildErrorUrl("emptyStrKey");
            return url;
        }
        var df = Common.currentDfInPlayer();
        if (df) {
            // use this form if DF is available, although we may not need to.
            url = Common.currentDfInPlayer().buildQcpUrl(strKey, preferredDomain);
        }
        else {
            // otherwise use this form
            if (preferredDomain) {
                url = QSettings._protocol + preferredDomain + "/q-qcp/" + strKey;
            }
            else {
                url = "/q-qcp/" + strKey;
            }
            if (window.location.search.toLowerCase().indexOf("bc=1") > -1) {
                var sep = Common.nextArgSep(url);
                url = url + sep + "cb=" + (DateUtils.msNow());
            }
        }
        return url;
    };
    QSettingsOne.prototype.buildStreamingQcpUrl = function (strKey) {
        if (this._isDesktopBrowser)
            return this.buildQcpUrlHelper(strKey, QSettings._contentDomain);
        else
            return Common.currentDfInPlayer().buildQcpUrl(strKey);
    };
    QSettingsOne.prototype.buildStillQcpUrl = function (strKey) {
        if (this._isDesktopBrowser)
            return this.buildQcpUrlHelper(strKey, QSettings._domainFull);
        else
            return Common.currentDfInPlayer().buildQcpUrl(strKey);
    };
    QSettingsOne.prototype.buildUaAndVersion = function () {
        return this.CleanedUserAgent + "_" + this.Version;
    };
    QSettingsOne.prototype.postUrl = function () {
        var url = this.relOrAbs();
        url += "/q-http?cb=" + DateUtils.msNow();
        url += this.sslAppendix(Common.isSecure);
        return url;
    };
    QSettingsOne.prototype.securePostUrl = function () {
        if (this._isDesktopBrowser)
            return "https://" + this._secureDomain + "/q-http?cb=" + DateUtils.msNow();
        else
            return this.postUrl();
    };
    QSettingsOne.prototype.buildPageAddress = function (strName, args) {
        var url = "/" + strName;
        if (args != undefined) {
            url += "?" + args;
        }
        if (this.BustCache) {
            url += (args == undefined) ? "?" : "&";
            url += "bc=1";
        }
        return url;
    };
    QSettingsOne.prototype.buildUrlPage = function (strName, args) {
        return this.buildPageAddress(strName + ".jsp", args);
    };
    QSettingsOne.prototype.buildSubmissionsUrl = function (args) {
        var value = this.relOrAbs();
        value += "/q-submissions?cmd=submit";
        if (args) {
            // start with ? or &... if so, strip it
            if ("?&".indexOf(args.substring(0)) == 0) {
                args = args.substring(1);
            }
            // and append to what we return
            value = value + "&" + args;
        }
        return value;
    };
    /**
     * Used only by web clients for building the URL needed
     * by the compose-peer-message iframe
     * @param recipient who gets this message (quid)
     * @param referralDfid what dataform was the sender on (if any)
     * @param link
     * @param title
     * @param isInInbox
     * @returns {string}
     */
    QSettingsOne.prototype.buildComposePeerMsgUrl = function (recipient, referralDfid, link, title, isInInbox) {
        if (!this._isDesktopBrowser)
            throw 'buildComposePeerMsgUrl not implemented for mobile';
        var result = "https://" + this._secureDomain +
            "/home/peerMessageCompose" +
            "?to=" + recipient +
            "&dfid=" + referralDfid +
            "&link=" + encodeURIComponent(link) +
            "&title=" + encodeURIComponent(title) +
            "&isInInbox=" + isInInbox; // tell a new iframe that it was called from inbox or not
        return result;
    };
    QSettingsOne.prototype.displayConfirmMessage = function (msg) {
        //confirm(msg);
    };
    // ///////////////////////////////////////////////////////////////////////////
    QSettingsOne.prototype.dfJsonUrl = function (strDataformID, whichCmd, additionalArgs) {
        var url = this.buildUrlCmd(whichCmd) + "&df=" + strDataformID;
        var u = queryString("u");
        if (u)
            url += "&u=" + u;
        var t = queryString("t");
        if (t)
            url += "&t=" + t;
        if (additionalArgs)
            url = url + "&" + additionalArgs;
        return url;
    };
    QSettingsOne.prototype.buildGetCommentsXmlUrl = function (strDataformID, highlightCommentId) {
        var baseurl = this.buildUrlCmd("getcmnt");
        var hiid = (highlightCommentId) ? ("&highlight=" + highlightCommentId) : "";
        return baseurl + "&dfid=" + strDataformID + hiid;
    };
    QSettingsOne.prototype.buildReferAFriendURL = function (strDfId, strEmailAddress) {
        // strEmailAddress is a semi-colon seperated list)
        return this.buildUrlCmd("refer") + "&dfid=" + strDfId + "&t=" + strEmailAddress;
    };
    QSettingsOne.prototype.buildPostsByUserXmlUrl = function (uid) {
        return this.buildUrlCmd("getcdf") + "&uid=" + uid;
    };
    ///////////////////////////////////////////////////////////////////////////
    QSettingsOne.prototype.bundledQcpUrl = function (strBundle, strKey) {
        if (this._isDesktopBrowser)
            return this.buildQcpUrlHelper(strBundle + "/" + strKey, QSettings._domainFull);
        else
            return this.buildStillQcpUrl(strBundle + "/" + strKey);
    };
    /////////////////////////////////////////////////////////////////////////////
    QSettingsOne.prototype.buildPlayerUrl = function (strdfid, strChannel, ns) {
        var args = "";
        var dfid = ScreenDoor.To(parseInt(strdfid, 10));
        if (strChannel !== undefined && strChannel !== null)
            args += "&cid=" + strChannel;
        if (queryString("ch") !== null) {
            args += "&back=channel";
        }
        else if (queryString("s") !== null) {
            args += "&back=search&s=" + queryString("s");
        }
        if (args !== "") {
            args = args.substring(1);
        }
        return this.buildPageAddress("player/" + dfid, args);
    };
    QSettingsOne.prototype.buildUploadUrl = function (type, id) {
        if (!this._isDesktopBrowser)
            throw 'buildUploadUrl not implemented for mobile';
        var qAuthCooklie = new QAuthCookie(readCookie("auth"));
        var uploadUrl = "/q-submissions?cmd=newFile&type=" + type +
            "&user=" + qAuthCooklie._userScreenDoor +
            "&pass=" + qAuthCooklie._creds +
            "&key=" + gQCredentials.ScreenDoorName + "_" + id;
        return uploadUrl;
    };
    QSettingsOne.prototype.getSearchUrl = function (extra) {
        var bc = "bc=" + DateUtils.msNow();
        if (extra)
            extra = extra + "&" + bc;
        else
            extra = bc;
        if (this._isDesktopBrowser)
            return 'http://' + this._nonSecureDomain + '/search?' + extra;
        else
            return this.buildPageAddress("search", extra);
    };
    QSettingsOne.prototype.parseDomain = function () {
        if (this._isDesktopBrowser)
            return this.parseDomainWeb();
        else
            return this.parseDomainMobile();
    };
    QSettingsOne.prototype.parseDomainWeb = function () {
        var loc = document.location.href;
        var doubleSlashPos = loc.indexOf("://") + 3;
        var strDomain = loc.substring(doubleSlashPos, loc.length - 1);
        var indexOfSlash = strDomain.indexOf("/");
        if (indexOfSlash >= 0) {
            strDomain = strDomain.substring(0, indexOfSlash);
        }
        return strDomain;
    };
    QSettingsOne.prototype.parseDomainMobile = function () {
        // desktop handled on construction,
        if (this._isDesktopBrowser)
            return "";
        if (theAppIFace.supportsSettings()) {
            // note that mobile is async
            theAppIFace.getSettingAsync("serverAddress", function (strDomain) {
                if (strDomain) {
                    var indexOfSlash = strDomain.indexOf("/");
                    if (indexOfSlash >= 0) {
                        strDomain = strDomain.substring(0, indexOfSlash);
                    }
                    this._contentDomain = strDomain;
                    this._domainFull = strDomain;
                    if (this._contentDomain.indexOf("quantiamd.com") >= 0) {
                        this._contentDomain = "myqcp.quantiamd.com";
                    }
                    if (strDomain.indexOf(".com") > -1 || strDomain.indexOf(".jp") > -1) {
                        strDomain = strDomain.replace(/www\./, "").replace(/my\./, "");
                    }
                    this._secureDomain = strDomain;
                }
            });
        }
        else {
            var loc = document.location.href;
            var doubleSlashPos = loc.indexOf("://") + 3;
            var strDomain = loc.substring(doubleSlashPos, loc.length - 1);
            var indexOfSlash = strDomain.indexOf("/");
            if (indexOfSlash >= 0) {
                strDomain = strDomain.substring(0, indexOfSlash);
            }
            this._contentDomain = strDomain;
            this._domainFull = strDomain;
            if (this._contentDomain.indexOf("quantiamd.com") >= 0) {
                this._contentDomain = "myqcp.quantiamd.com";
            }
            if (strDomain.indexOf(".com") > -1 || strDomain.indexOf(".jp") > -1) {
                strDomain = strDomain.replace(/www\./, "").replace(/my\./, "");
            }
            this._secureDomain = strDomain;
        }
        return this._secureDomain;
    };
    // ///////////////////////////////////////////////////////////////////////////
    QSettingsOne.parseProtocolFromPageUrl = function () {
        var u = window.location.href;
        var c = u.indexOf(":");
        if (c > -1) {
            return u.substring(0, c) + "://";
        }
        return "http://";
    };
    QSettingsOne.makeNonSecureDomain = function (url) {
        url = url.replace('secure.', '');
        return url;
    };
    return QSettingsOne;
}());
var QSettings = new QSettingsOne();
document.addEventListener("DOMContentLoaded", QSettings.parseDomain.bind(QSettings), false);




// DateUtils.js

/// <reference path="Window.d.ts" />
var DateUtils = (function () {
    function DateUtils() {
    }
    DateUtils.formatTo2Letters = function (input) {
        var str = input.toString();
        if (str.length === 0)
            str = "00";
        else if (str.length === 1)
            str = "0" + str;
        return str;
    };
    DateUtils.getClockTime = function (t) {
        var hour = t.getHours();
        var minute = t.getMinutes();
        var second = t.getSeconds();
        var ap = "AM";
        if (hour > 11) {
            ap = "PM";
        }
        if (hour > 12) {
            hour = hour - 12;
        }
        if (hour === 0) {
            hour = 12;
        }
        return DateUtils.formatTo2Letters(hour) +
            ':' + DateUtils.formatTo2Letters(minute) +
            ':' + DateUtils.formatTo2Letters(second) + ' ' + ap;
    };
    DateUtils.CurrentDateToString = function () {
        // 03/03/2007 15:56:38
        return DateUtils.dateToString(new Date());
    };
    // Returns yyyy-mm-dd hh:mm:ss
    DateUtils.dateToServerTimeString3 = function (date) {
        if (!date)
            return "";
        var month = DateUtils.formatTo2Letters(date.getMonth() + 1);
        var day = DateUtils.formatTo2Letters(date.getDate());
        var year = date.getFullYear();
        var min = DateUtils.formatTo2Letters(date.getMinutes());
        var hour = DateUtils.formatTo2Letters(date.getHours());
        var sec = DateUtils.formatTo2Letters(date.getSeconds());
        return ('' + year + '-' + month + '-' + day + ' ' + hour + ':' + min + ':' + sec);
    };
    DateUtils.dateToString = function (date) {
        if (!date)
            return "";
        var month = DateUtils.formatTo2Letters(date.getMonth() + 1);
        var day = DateUtils.formatTo2Letters(date.getDate());
        var year = date.getFullYear();
        var min = DateUtils.formatTo2Letters(date.getMinutes());
        var hour = DateUtils.formatTo2Letters(date.getHours());
        var sec = DateUtils.formatTo2Letters(date.getSeconds());
        return ('' + month + '/' + day + '/' + year + ' ' + hour + ':' + min + ':' + sec);
    };
    DateUtils.toAbbreviatedDate = function (dateArg) {
        // returns string formatted like Apr 4, 2007
        if (!dateArg) {
            return "";
        }
        var month = DateUtils._luMonths[dateArg.getMonth() + 1];
        var dayOfMonth = dateArg.getDate();
        if (Pageparams.language === 'ja') {
            return dateArg.getFullYear() + "\u5E74" + (dateArg.getMonth() + 1) + "\u6708" + dayOfMonth + "\u65E5";
        }
        return month + " " + dayOfMonth + ", " + dateArg.getFullYear();
    };
    DateUtils.toAbbreviatedDateAndTime = function (dateObj) {
        return DateUtils.toAbbreviatedDate(dateObj) + " " + DateUtils.toHrsMinString(dateObj);
    };
    DateUtils.toNumberedDate = function (dateObj) {
        if (!dateObj)
            return "";
        var month = dateObj.getMonth() + 1;
        var date = dateObj.getDate();
        var year = "" + dateObj.getFullYear();
        year = year.substring(2);
        if (Pageparams.language === 'ja') {
            return dateObj.getFullYear() + "\u5E74" + month + "\u6708" + date + "\u65E5";
        }
        return "" + month + "/" + date + "/" + year;
    };
    DateUtils.toNumberedDateAndTime = function (dateObj) {
        return DateUtils.toNumberedDate(dateObj) + " " + DateUtils.toHrsMinString(dateObj);
    };
    DateUtils.toNumberedDateAndTimeUpper = function (dateObj) {
        return DateUtils.toNumberedDate(dateObj) + " " + DateUtils.toHrsMinStringUpper(dateObj);
    };
    DateUtils.toCommentStyleDateTime = function (dateObj) {
        if (!dateObj)
            return "";
        var datestr = "";
        var timestr = DateUtils.toHrsMinString(dateObj);
        if (PageFlavor.isSPlayerFamily()) {
            // FIXME:  need language specific control string to do replacement
            datestr = DateUtils.toLocaleNetrulYYYYMMDD(dateObj);
            return datestr + " " + timestr;
        }
        else {
            datestr = DateUtils.toLongDate(dateObj);
            if (!Pageparams.language || Pageparams.language.toLowerCase() == 'en') {
                return datestr + " at " + timestr;
            }
            if (Pageparams.language.toLowerCase() == 'ja') {
                return datestr + " " + timestr;
            }
            return datestr + " at " + timestr;
        }
    };
    DateUtils.toLocaleNetrulYYYYMMDD = function (dateObj) {
        var month = DateUtils.formatTo2Letters(dateObj.getMonth() + 1);
        var day = DateUtils.formatTo2Letters(dateObj.getDate());
        var yy = dateObj.getFullYear();
        return yy + "-" + month + "-" + day;
    };
    DateUtils.toLongDate = function (dateObj) {
        if (!dateObj)
            return "";
        if (!Pageparams.language || Pageparams.language.toLowerCase() == 'en') {
            var year = "" + dateObj.getFullYear();
            var month = DateUtils._strMonthsEn[dateObj.getMonth()];
            var date = "" + dateObj.getDate();
            return month + " " + date + ", " + year;
        }
        if (Pageparams.language.toLowerCase() === 'ja') {
            return dateObj.getFullYear() + "\u5E74" + (dateObj.getMonth() + 1) + "\u6708" + dateObj.getDate() + "\u65E5";
        }
        return "";
    };
    DateUtils.toHrsMinString = function (dateObj) {
        // returns string formatted as "hh:mmam" such as 10:30am
        if (!dateObj)
            return "";
        var hour = dateObj.getHours();
        var amPm = "am";
        if (hour > 11) {
            hour = hour - 12;
            amPm = "pm";
        }
        if (hour === 0) {
            hour = 12;
        }
        var min = "" + dateObj.getMinutes();
        if (parseInt(min, 10) < 10) {
            min = "0" + min;
        }
        return hour + ":" + min + amPm;
    };
    DateUtils.toHrsMinStringUpper = function (dateObj) {
        // returns string formatted as "hh:mmam" such as 10:30am
        if (!dateObj)
            return "";
        var hour = dateObj.getHours();
        var amPm = " AM";
        if (hour > 11) {
            hour = hour - 12;
            amPm = " PM";
        }
        if (hour === 0) {
            hour = 12;
        }
        var min = "" + dateObj.getMinutes();
        if (parseInt(min, 10) < 10) {
            min = "0" + min;
        }
        return hour + ":" + min + amPm;
    };
    /*
     * Date from server time
     * input in format of "mm/dd/yyyy hh:mm:ss"
     */
    DateUtils.FromServerTime1 = function (serverTime) {
        var newDate = null;
        try {
            var pieces = serverTime.split(" ");
            var datepieces = pieces[0].split("/");
            var newdatestr = DateUtils._luMonths[parseInt(datepieces[0], 10)] + " " + datepieces[1] + ", " + datepieces[2] + " " + pieces[1];
            newDate = new Date(newdatestr);
        }
        catch (err) {
            newDate = new Date();
        }
        return newDate;
    };
    /*
     * parses datetime in format of 02/16/07 10:19:07 (hours/min/seconds is
     * optional)
     */
    DateUtils.FromServerTime2 = function (serverTime) {
        // default data
        var year = 1901;
        var month = 0;
        var day = 1;
        var hours = 0;
        var minutes = 0;
        var seconds = 0;
        var milliseconds = 0;
        var dateNow = new Date();
        try {
            var pieces = serverTime.split(" ");
            if (pieces.length > 0) {
                if (pieces[0]) {
                    var datepieces = pieces[0].split("/");
                    if (datepieces.length == 3) {
                        month = parseInt(datepieces[0], 10) - 1;
                        day = parseInt(datepieces[1], 10);
                        year = parseInt(datepieces[2], 10);
                        if (year < 100) {
                            year = 2000 + year;
                            if (year > dateNow.getFullYear()) {
                                year -= 100;
                            }
                        }
                        if (pieces.length > 1 && pieces[1] !== null) {
                            var time = pieces[1].split(":");
                            if (time.length > 0) {
                                hours = Number(time[0]);
                            }
                            if (time.length > 1) {
                                minutes = Number(time[1]);
                            }
                            if (time.length > 2) {
                                seconds = Number(time[2]);
                            }
                        }
                    }
                }
            }
        }
        catch (e) {
        }
        return new Date(year, month, day, hours, minutes, seconds, milliseconds);
    };
    DateUtils.msFromServerTime3 = function (strServerTime) {
        var obj = DateUtils.fromServerTime3(strServerTime);
        return obj.getTime();
    };
    DateUtils.fromServerTime3 = function (serverTime) {
        // DateFromServerDateTime3
        // parses datetime in format of 2007-03-29 15:15:40.0 (hours/min/seconds is optional)
        if (!serverTime)
            return null;
        var pieces = serverTime.split(" ");
        var datepieces = pieces[0].split("-");
        var time = pieces[1].split(":");
        var millis = 0;
        var time2 = time[2].split(".");
        if (time2.length > 1) {
            // convert fractional (decimal) part to millis
            millis = parseFloat('.' + time2[1]);
            if (isNaN(millis))
                millis = 0;
            else
                millis = Math.floor(millis * 1000);
        }
        // new Date(year, month, day, hours, minutes, seconds, milliseconds)
        return new Date(parseInt(datepieces[0]), parseInt(datepieces[1], 10) - 1, parseInt(datepieces[2], 10), parseInt(time[0], 10), parseInt(time[1], 10), parseInt(time2[0], 10), millis);
    };
    /*
     * parses datetime in format of '1999'
     */
    DateUtils.FromYear = function (strYear) {
        // default data
        var year = strYear;
        var month = 0;
        var day = 1;
        var hours = 0;
        var minutes = 0;
        var seconds = 0;
        var milliseconds = 0;
        return new Date(year, month, day, hours, minutes, seconds, milliseconds);
    };
    DateUtils.extractTimeZoneString = function (startTime) {
        var d = new Date(Number(startTime));
        var gmtHours = -d.getTimezoneOffset() / 60;
        var gmtHoursStr = "GMT " + gmtHours;
        if (gmtHours === 0) {
            gmtHoursStr = "GMT";
        }
        if (gmtHours > 0) {
            gmtHoursStr = "GMT +" + gmtHours;
        }
        // alert(gmtHoursStr);
        // this makes sure europe or anything east of EST gets a GMT representation
        if (gmtHours > -4) {
            return gmtHoursStr;
        }
        var rawString = d.toString().toLowerCase();
        // alert(rawString);
        if (rawString.indexOf('eastern') !== -1) {
            return (rawString.indexOf('standard') !== -1) ? 'EST' : 'EDT';
        }
        if (rawString.indexOf('pacific') !== -1) {
            return (rawString.indexOf('standard') !== -1) ? 'PST' : 'PDT';
        }
        if (rawString.indexOf('mountain') !== -1) {
            return (rawString.indexOf('standard') !== -1) ? 'MST' : 'MDT';
        }
        if (rawString.indexOf('central') !== -1) {
            return (rawString.indexOf('central') !== -1) ? 'CST' : 'CDT';
        }
        // lets try these (found on iphone and IE)
        // for IE
        if (rawString.indexOf('est') !== -1) {
            return 'EST';
        }
        if (rawString.indexOf('edt') !== -1) {
            return 'EDT';
        }
        if (rawString.indexOf('cst') !== -1) {
            return 'CST';
        }
        if (rawString.indexOf('cdt') !== -1) {
            return 'CDT';
        }
        if (rawString.indexOf('mst') !== -1) {
            return 'MST';
        }
        if (rawString.indexOf('mdt') !== -1) {
            return 'MDT';
        }
        if (rawString.indexOf('pst') !== -1) {
            return 'PST';
        }
        if (rawString.indexOf('pdt') !== -1) {
            return 'PDT';
        }
        //we use hours from GMT
        return gmtHoursStr;
    };
    DateUtils.convertToClientTimeMs = function (serverTimeObj) {
        var serverMillis = serverTimeObj.getTime();
        var clientMillis1 = serverMillis;
        var clientMillis2 = serverMillis;
        var df = Common.currentDfInPlayer();
        if (df) {
            var diffMs = df.calcClientTimeDiffMs();
            clientMillis1 = serverMillis + diffMs;
            clientMillis2 = clientMillis1;
        }
        if (DateUtils.serverTimeDelta) {
            clientMillis2 = serverMillis + DateUtils.serverTimeDelta;
        }
        return clientMillis2;
    };
    DateUtils.convertToClientTimeObj = function (serverTimeObj) {
        return new Date(DateUtils.convertToClientTimeMs(serverTimeObj));
    };
    DateUtils.getCurrentServerTimeMs = function () {
        var delta = 0;
        if (DateUtils.serverTimeDelta != Number.MIN_VALUE)
            delta = DateUtils.serverTimeDelta;
        return new Date().getTime() + delta;
    };
    DateUtils.initServerTime = function (strServerTime) {
        DateUtils.strOrigServerTime = strServerTime;
        DateUtils.clientTimeAtServerTime = new Date();
        DateUtils.strClientTimeAtServertime = DateUtils.clientTimeAtServerTime.toString();
        DateUtils.serverTime = DateUtils.fromServerTime3(strServerTime);
        DateUtils.strOrigServerTime3 = DateUtils.dateToServerTimeString3(DateUtils.serverTime);
        DateUtils.serverTimeDelta = DateUtils.clientTimeAtServerTime - DateUtils.serverTime;
    };
    // Used by mobile panel initialization
    DateUtils.initCurrentServerTimeGivenPastServerAndClientTime = function (serverDfOpenTimeMs, clientDfOpenTimeMs) {
        var currentServerTime = DateUtils.msNow() + serverDfOpenTimeMs - clientDfOpenTimeMs;
        var strServerTime = DateUtils.dateToServerTimeString3(new Date(currentServerTime));
        DateUtils.initServerTime(strServerTime);
    };
    DateUtils.debugAlert = function (label) {
        var msg = "label: " + label +
            "  \norig Server: " + DateUtils.strOrigServerTime +
            "  \norig Server: " + DateUtils.strOrigServerTime3 +
            "  \nclient: " + DateUtils.strClientTimeAtServertime +
            "  \ndelta: " + DateUtils.serverTimeDelta;
        alert(msg);
    };
    DateUtils.msNow = function () {
        return (new Date()).getTime();
    };
    DateUtils.msElapsedSince = function (previousTimeMs) {
        // return magnitude of difference instead of absolute difference
        var msDiff = DateUtils.msNow() - previousTimeMs;
        return Math.abs(msDiff);
    };
    DateUtils.msElapsedSinceInit = function () {
        return DateUtils.msElapsedSince(DateUtils.serverTime.getTime());
    };
    DateUtils.strOrigServerTime = "";
    DateUtils.strClientTimeAtServertime = "";
    DateUtils.strOrigServerTime3 = "";
    DateUtils.serverTime = null;
    DateUtils.clientTimeAtServerTime = null;
    DateUtils.serverTimeDelta = Number.MIN_VALUE;
    DateUtils._luMonths = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    DateUtils._strMonthsEn = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    return DateUtils;
}());




// QAuthCookie.js

var QAuthCookie = (function () {
    function QAuthCookie(strVal) {
        this._userScreenDoor = "";
        this._creds = "";
        this._legacyname = "";
        this._authStatus = "";
        var t;
        if (!strVal)
            return;
        var parts = strVal.split(QAuthCookie.partSep);
        if (parts.length > 0)
            this._userScreenDoor = parts[0];
        if (parts.length > 1)
            this._creds = parts[1];
        if (parts.length > 2)
            this._legacyname = parts[2];
        // ignore legacy parts not marked as 
        if (parts.length > 3) {
            t = parts[3];
            if (t.lastIndexOf(QAuthCookie.authStatusTag, 0) === 0)
                this._authStatus = t;
        }
        if (parts.length > 4) {
            t = parts[4];
            if (t.lastIndexOf(QAuthCookie.authStatusTag, 0) === 0)
                this._authStatus = t;
        }
    }
    QAuthCookie.prototype.getStrVal = function () {
        return QAuthCookie.buildStrVal(this._userScreenDoor, this._creds, this._authStatus);
    };
    QAuthCookie.prototype.updateStatus = function (newStatus) {
        if (!newStatus)
            return;
        if (newStatus == QAuthCookie.authStatusFull)
            this._authStatus = "";
        else
            this._authStatus = QAuthCookie.authStatusTag + newStatus;
    };
    QAuthCookie.buildStrVal = function (userScreenDoor, creds, authStatus) {
        var s = userScreenDoor;
        s += (QAuthCookie.partSep + creds);
        s += (QAuthCookie.partSep + userScreenDoor);
        if (authStatus && (authStatus != QAuthCookie.authStatusFull))
            s += (QAuthCookie.partSep + authStatus);
        return s;
    };
    // contents of Auth cookie have varied over time,
    // so the class needs to respect old formats.
    QAuthCookie.partSep = "___";
    QAuthCookie.authStatusTag = "au!";
    // should match values from Java LoginStatus enum
    QAuthCookie.authStatusFull = "FULL";
    QAuthCookie.authStatusAnonymous = "ANONYMOUS";
    QAuthCookie.authStatusLimitedConfirmed = "LIMITED_CONFIRMED";
    QAuthCookie.authStatusLimitedUnconfirmed = "LIMITED_UNCONFIRMED";
    QAuthCookie.authStatusLimitedAutoreg = "LIMITED_AUTOREG";
    return QAuthCookie;
}());




// AccountInfoBase.js

var AccountInfoBase = (function () {
    function AccountInfoBase() {
    }
    AccountInfoBase.Title = "";
    AccountInfoBase.FirstName = "";
    AccountInfoBase.LastName = "";
    AccountInfoBase.FullName = "";
    AccountInfoBase.DisplayName = "";
    AccountInfoBase.NameInPublicForums = "";
    AccountInfoBase.Degree = "";
    AccountInfoBase.Suffix = "";
    AccountInfoBase.Locale = "";
    AccountInfoBase.Domain = "";
    AccountInfoBase.BaseHostAddress = "";
    AccountInfoBase.PrimaryLanguage = "";
    AccountInfoBase.DevicePartnerCode = "";
    AccountInfoBase.Country = "";
    AccountInfoBase.Languages = "";
    AccountInfoBase.PreferredSlideFormat = "";
    AccountInfoBase.PreferHtml5Audio = "";
    return AccountInfoBase;
}());
var OldAccountInfo;
if (AccountInfo !== undefined) {
    OldAccountInfo = AccountInfo;
}
else {
    OldAccountInfo = new AccountInfoBase();
}
var AccountInfo = new AccountInfoBase();
AccountInfo.PrimaryLanguage = OldAccountInfo.PrimaryLanguage;
AccountInfo.DevicePartnerCode = OldAccountInfo.DevicePartnerCode;
AccountInfo.Country = OldAccountInfo.Country;
AccountInfo.Languages = OldAccountInfo.Languages;
AccountInfo.PreferredSlideFormat = OldAccountInfo.PreferredSlideFormat;
AccountInfo.PreferHtml5Audio = OldAccountInfo.PreferHtml5Audio;
// initialize Pageparams if necessary
var Pageparams = (typeof Pageparams == "undefined" ? {} : Pageparams);




// QCredentials.js

//xnclude "XML.js"
/// <reference path="DateUtils.ts" />
/// <reference path="PasswordPrompt.ts" />
/// <reference path="Common.d.ts" />
/// <reference path="ActivityMonitor.ts" />
//File Descriptions:
//Global object that stores data necessary to authenticate with server
//(on initial login when user enters username/password; and also whatever
// will be required by the server to authenticate all other datacalls
var QCredentialsImpl = (function () {
    function QCredentialsImpl() {
        this.ScreenDoorName = "";
        this.UserCode = "";
        this.PhotoVersion = "";
        this.Token = "";
        this.unauthIDType = "None";
        this.unauthIDValue = 0;
        this.ForciblyDenied = false;
        this.LoginStatus = "";
        this.HasJustLoggedIn = false;
        this.pwdDlg = null;
        this.unauthIDType = "None";
        this.unauthIDValue = 0;
        this.LoginStatus = QAuthCookie.authStatusFull;
        try {
            this.ServerName = window.location.host;
        }
        catch (err) {
        }
        this.HasJustLoggedIn = false;
        if (typeof doOnPageReady != "undefined") {
            doOnPageReady(this.init.bind(this));
        }
    }
    QCredentialsImpl.prototype.init = function () {
        setTimeout(this.delayedInit.bind(this), 100);
    };
    QCredentialsImpl.prototype.delayedInit = function () {
        if (this.isLoginLimited() && Pageparams.requireFullAuth) {
            this.launchPasswordDlg(false);
        }
    };
    QCredentialsImpl.prototype.loadCredentials = function () {
        if (!Common.userCookie) {
            Common.userCookie = readCookie("com.quantia.user");
        }
        if (Common.userCookie) {
            var qAuthCookie = new QAuthCookie(Common.userCookie);
            if (qAuthCookie._creds) {
                gQCredentials.Token = qAuthCookie._creds;
                return true;
            }
            return false;
        }
        else if (!gQCredentials.isAnonymous()) {
            return false;
        }
        if (gQCredentials.isAnonymous()) {
            gQCredentials.Token = "webapp";
        }
    };
    /*
     * For browsers, check cookies to see if we are already logged in
     * For mobile apps, auth comes per each request.
     */
    QCredentialsImpl.prototype.loadCachedCreds = function (redirectToHomeIfNotLoggedIn) {
        var strVal = readCookie("auth");
        if (!strVal)
            strVal = readCookie("com.quantia.user");
        if (strVal) {
            var qAuthCookie = new QAuthCookie(strVal);
            if (qAuthCookie._creds) {
                this.Token = qAuthCookie._creds;
                // if our cookie doesn't match what the server gave us - force a refresh
                if (this.ScreenDoorName.toLowerCase() != qAuthCookie._userScreenDoor.toLowerCase()
                    && !this.ForciblyDenied) {
                    window.location.reload(true);
                    return false;
                }
            }
        }
        else if (!this.isAnonymous()) {
            // if there is no cookie - but we think we aren't using the guest account, reload
            window.location.reload(true);
            return false;
        }
        if (redirectToHomeIfNotLoggedIn && this.isAnonymous()) {
            window.location.href = "/";
            return false;
        }
        if (this.isAnonymous()) {
            this.Token = "webapp";
        }
        return true;
    };
    QCredentialsImpl.prototype.loadFromResponse = function (response) {
        if (!response)
            return;
        // type of response might be string or object, depending on caller?
        // Ajax vs JSONP?
        var respObj = null;
        if (typeof (response === "string"))
            respObj = Common.jsonParse(response);
        else
            respObj = response;
        var newCreds = respObj.qcreds;
        if (!newCreds)
            return;
        this.ScreenDoorName = newCreds.ScreenDoorName;
        this.UserCode = newCreds.UserCode;
        this.PhotoVersion = newCreds.PhotoVersion;
        this.LoginStatus = newCreds.LoginStatus;
        this.ForciblyDenied = newCreds.ForciblyDenied;
        this.HasJustLoggedIn = false; // flag used for resume behaviors, not federation
        if (newCreds.pls && newCreds.plt) {
            this.createLoginCookie(newCreds.ScreenDoorName, newCreds.pls, newCreds.plt, false);
        }
        return true;
    };
    QCredentialsImpl.prototype.AttemptLogout = function (eventDesc) {
        this.loadCachedCreds(false);
        if (this.ScreenDoorName != "" && this.Token != "") {
            Common.attemptWindowQuit();
            var xmlDocument = XML.CreateDocument("<logout></logout>");
            var element = xmlDocument.documentElement;
            element.setAttribute("id", this.ScreenDoorName);
            if (eventDesc)
                element.setAttribute("eventDesc", eventDesc);
            element.setAttribute("password", this.Token);
            element.setAttribute("deviceclass", "web");
            element.setAttribute("devicetype", "web");
            Ajax.queueXmlToServer(QSettings.postUrl(), xmlDocument);
        }
    };
    QCredentialsImpl.prototype.GetPartner = function () {
        this.UpdatePartner();
        return readCookie("partner");
    };
    QCredentialsImpl.prototype.EnsurePartnerCode = function (partnerCode) {
        if (partnerCode == null || partnerCode == "" || partnerCode == "false") {
            return;
        }
        var currentPartners = [];
        var currentPartnerCookie = readCookie("partner");
        if (currentPartnerCookie) {
            currentPartners = currentPartnerCookie.split(/[~;,]/);
        }
        var hasFound = false;
        for (var i = 0; i < currentPartners.length; i++) {
            if (currentPartners[i] == partnerCode) {
                hasFound = true;
                break;
            }
        }
        if (!hasFound) {
            currentPartners.push(partnerCode);
            var newCookieValue = currentPartners.join("~");
            createCookie("partner", newCookieValue, 90 * Common.ONE_MINUTE_IN_DAYS);
        }
    };
    QCredentialsImpl.prototype.UpdatePartner = function (pCode) {
        this.EnsurePartnerCode(pCode);
        if (typeof queryString != 'undefined') {
            var partnerCode = queryString("partner");
            this.EnsurePartnerCode(partnerCode);
        }
    };
    // Marketing Campaign Code (mcc) cookie holds a code for tracking campaigns
    // and optionally the dfid at user registration, semicolon separated
    // mcc[~reg_df_id]
    //
    QCredentialsImpl.prototype.AddDfIdToMarketingCode = function (dfId) {
        if (dfId) {
            var mCode = this.GetMarketingCampaignCode();
            if (mCode.indexOf("~") > -1)
                return;
            mCode = mCode + "~" + dfId;
            this.EnsureMarketingCampaignCode(mCode);
        }
    };
    QCredentialsImpl.prototype.UpdateMarketingCampaignCode = function () {
        if (typeof queryString != 'undefined') {
            var marketingCampaignCode = queryString("m");
            this.EnsureMarketingCampaignCode(marketingCampaignCode);
        }
    };
    QCredentialsImpl.prototype.EnsureMarketingCampaignCode = function (mCode) {
        if (!mCode || mCode == "false") {
            return;
        }
        // Replace any old cookie with new IF
        // mcc value (first piece) is new
        // OR if we are setting a new non-empty dfID (second piece)
        var priorCode = readCookie("mcc");
        if (priorCode) {
            priorCode = priorCode.split("~")[0];
        }
        var newPieces = mCode.split("~");
        if (newPieces.length < 2 || newPieces[1] == '') {
            // No dfID being set.  If not changing mCode, just quit
            // so that we do not lose existing registration-dfID
            // This also prevents resetting cookie timeout every time we load a df
            if (newPieces[0] == priorCode)
                return;
        }
        createCookie("mcc", mCode, 90 * Common.ONE_MINUTE_IN_DAYS);
    };
    QCredentialsImpl.prototype.GetMarketingCampaignCode = function () {
        this.EnsureMarketingCampaignCode();
        return readCookie("mcc");
    };
    QCredentialsImpl.prototype.UpdateRegid = function () {
        if (typeof queryString != 'undefined') {
            var regid = queryString("rgid");
            this.EnsureRegid(regid);
        }
    };
    QCredentialsImpl.prototype.EnsureRegid = function (regid) {
        if (!regid || regid == "false") {
            return;
        }
        createCookie("joinquantiamd", regid, 1);
    };
    QCredentialsImpl.prototype.updateCookiesAtStartup = function () {
        gQCredentials.UpdatePartner();
        gQCredentials.UpdateMarketingCampaignCode();
        gQCredentials.UpdateRegid();
    };
    QCredentialsImpl.prototype.createLoginXml = function (username, password) {
        var xmlAuth = XML.CreateDocument("<authenticate></authenticate>");
        var authElt = xmlAuth.documentElement;
        authElt.setAttribute("id", username);
        authElt.setAttribute("password", password);
        authElt.setAttribute("web", "true");
        authElt.setAttribute("deviceclass", "web");
        authElt.setAttribute("devicetype", "web");
        var dfScreen = null;
        if (typeof queryString != 'undefined') {
            if (queryString('u')) {
                // referrer
                authElt.setAttribute("u", queryString('u'));
            }
            if (queryString('c')) {
                // dataform screendoor
                dfScreen = queryString('c');
            }
            else if (location.href.match(/\/player\/[a-z]{4,}/)) {
                dfScreen = location.href.match(/\/player\/[a-z]{4,}/);
                if (dfScreen) {
                    dfScreen = dfScreen[0].substr(8);
                }
            }
            else if (location.href.match(/df=([0-9]{4,})/)) {
                dfScreen = location.href.match(/df=([0-9]{4,})/);
                if (dfScreen) {
                    dfScreen = dfScreen[0].substr(3);
                    dfScreen = ScreenDoor.To(dfScreen);
                }
            }
        }
        if (dfScreen) {
            authElt.setAttribute("c", dfScreen);
        }
        return (xmlAuth);
    };
    QCredentialsImpl.prototype.AttemptLogin = function (username, password, resultCallback, rememberMe) {
        var tempThis = this;
        if (false != rememberMe)
            rememberMe = true;
        storeTimeZone();
        var xmlAuth = this.createLoginXml(username, password);
        function onLoginSuccess(results) {
            var authResults = XML.CreateDocument(results);
            var docElt = authResults.documentElement;
            if (authResults && docElt.getAttribute("type") == "success") {
                if ((typeof (BrowserPlayer) != 'undefined') && BrowserPlayer) {
                    if (BrowserPlayer.objDataform)
                        BrowserPlayer.objDataform.onIdentityChange();
                }
                Common.addDataLayerEvent({ 'event': 'loginSuccess' });
                tempThis.HasJustLoggedIn = true;
                tempThis.LoginStatus = QAuthCookie.authStatusFull;
                // var serverUsername = authResults.documentElement.getAttribute("user_name");
                tempThis.ScreenDoorName = docElt.getAttribute("screen_door_name");
                var pls = docElt.getAttribute("pls");
                var plt = docElt.getAttribute("plt");
                var act = docElt.getAttribute("act");
                if (pls && plt) {
                    tempThis.Token = pls + "_" + plt;
                    tempThis.createLoginCookie(tempThis.ScreenDoorName, pls, plt, rememberMe);
                    tempThis.createLastActivityCookies(act);
                    createCookie("referralURI", "", -1);
                    resultCallback(true, null);
                }
                else {
                    resultCallback(false, QSTR.serverError);
                }
            }
            else {
                Common.addDataLayerEvent({ 'event': 'loginError' });
                results = QSTR.loginFailed;
                resultCallback(false, results);
            }
        }
        function onLoginFailure(errorMessage) {
            resultCallback(false, errorMessage);
        }
        Ajax.postAsXml(QSettings.postUrl(), xmlAuth, onLoginSuccess, onLoginFailure);
    };
    QCredentialsImpl.prototype.createLoginCookie = function (userScreenDoor, pls, plt, rememberMe) {
        QAuthCookie.buildStrVal(userScreenDoor, pls, "");
        var cookieAgeDays = (rememberMe) ? 30 : 0;
        createCookie("auth", QAuthCookie.buildStrVal(userScreenDoor, pls, ""), cookieAgeDays);
        var secure = true;
        createCookie("secure.auth", QAuthCookie.buildStrVal(userScreenDoor, pls + "_" + plt, ""), cookieAgeDays, secure);
    };
    QCredentialsImpl.prototype.updateLoginStatus = function (newStatus) {
        this.LoginStatus = newStatus;
        var strCookieVal = readCookie("auth");
        var qAuthCookie = null;
        var cookieAgeDays = 30;
        if (strCookieVal) {
            qAuthCookie = new QAuthCookie(strCookieVal);
            qAuthCookie.updateStatus(newStatus);
            createCookie("auth", qAuthCookie.getStrVal(), cookieAgeDays);
        }
        strCookieVal = readCookie("secure.auth");
        if (strCookieVal) {
            qAuthCookie = new QAuthCookie(strCookieVal);
            qAuthCookie.updateStatus(newStatus);
            var secure = true;
            createCookie("secure.auth", qAuthCookie.getStrVal(), cookieAgeDays, secure);
        }
    };
    QCredentialsImpl.prototype.createLastActivityCookies = function (act) {
        var secure = true;
        createCookie("act", "" + DateUtils.msNow(), 0);
        // and if we have a secure key, set it, too
        if (act) {
            createCookie("activityKey", act, 0, secure);
        }
    };
    QCredentialsImpl.prototype.DeleteCachedCredentials = function () {
        createCookie("auth", "", -1);
        createCookie("secure.auth", "", -1);
        createCookie("com.quantia.user", "", -1);
        createCookie("com.quantia.proxy", "", -1);
        createCookie("mcc", "", -1);
        createCookie("act", "", -1);
        createCookie("joinquantiamd", "", -1);
        createCookie("feed", "", -1);
    };
    QCredentialsImpl.prototype.getServerName = function () {
        if (this.ServerName === undefined || this.ServerName === null) {
            this.ServerName = location.host;
        }
        return this.ServerName;
    };
    QCredentialsImpl.prototype.setUnauthID = function (unauthIDType, unauthIDValue) {
        this.unauthIDType = unauthIDType;
        this.unauthIDValue = unauthIDValue;
        if (unauthIDType == 'PI_UID') {
            createCookie("UID", "" + unauthIDValue);
        }
    };
    QCredentialsImpl.prototype.isAnonymous = function () {
        return (this.LoginStatus == QAuthCookie.authStatusAnonymous); // must match Java enum
    };
    QCredentialsImpl.prototype.isLoginLimited = function () {
        return (this.LoginStatus == QAuthCookie.authStatusLimitedConfirmed ||
            this.LoginStatus == QAuthCookie.authStatusLimitedAutoreg ||
            this.LoginStatus == QAuthCookie.authStatusLimitedUnconfirmed);
    };
    QCredentialsImpl.prototype.isLoginLimited_UnconfirmedOrAutoreg = function () {
        return (this.LoginStatus == QAuthCookie.authStatusLimitedUnconfirmed ||
            this.LoginStatus == QAuthCookie.authStatusLimitedAutoreg);
    };
    QCredentialsImpl.prototype.isLoginLimited_Autoreg = function () {
        return (this.LoginStatus == QAuthCookie.authStatusLimitedAutoreg);
    };
    QCredentialsImpl.prototype.isLoginLimited_Unconfirmed = function () {
        return (this.LoginStatus == QAuthCookie.authStatusLimitedUnconfirmed);
    };
    QCredentialsImpl.prototype.launchPasswordDlg = function (showCloseButton) {
        // called when user has a limited login but requested
        // action requires full login.  User is given a chance to
        // enter a password so that action might succeed.
        var emailAddr = Common.getCreatePwdEmailCookieIfValid();
        if (emailAddr) {
            // Note special case that happens after a one-click registration:
            // User has never entered a password but we DO have
            // cookie data that indicates session started from the
            // registration click.  So, let the user create a password and proceed.
            Common.openResetPassword(showCloseButton);
        }
        else {
            var captionElt = q$('popupPwDlgCaption');
            captionElt.innerText = "Password required";
            var msgElt = q$('popupPwDlgMsg');
            msgElt.innerText = QSTR.messageLockedInfo;
            var dlgCloseElt = q$('popupPwDlgClose');
            if (showCloseButton) {
                dlgCloseElt.addEventListener('click', this.closePasswordPopup.bind(this));
            }
            else {
                Common.chide(dlgCloseElt);
            }
            this.pwdDlg = new PasswordPrompt('popupPwDlg', this.popupPasswordSuccess.bind(this), this.popupPasswordFailure.bind(this));
            this.pwdDlg.showDlg();
        }
    };
    QCredentialsImpl.prototype.closePasswordPopup = function () {
        if (!this.pwdDlg)
            return;
        this.pwdDlg.hideDlg();
    };
    // referenced explicitly in FMT
    QCredentialsImpl.prototype.checkPasswordFromPopup = function () {
        if (!this.pwdDlg)
            return;
        this.pwdDlg.checkPassword();
    };
    QCredentialsImpl.prototype.popupPasswordSuccess = function (respDoc) {
        var act = respDoc.documentElement.getAttribute("act");
        gQCredentials.createLastActivityCookies(act);
        ActivityMonitor.recordActivity();
        gQCredentials.updateLoginStatus(QAuthCookie.authStatusFull);
        var pwElt = q$('popupPwDlgPwd');
        pwElt.value = "";
        var errElt = q$('popupPwDlgError');
        errElt.innerHTML = QSTR.loginPasswordIncorrectText;
        this.pwdDlg.hideDlg();
        this.pwdDlg = null;
        Common.quickReload();
    };
    QCredentialsImpl.prototype.popupPasswordFailure = function () {
        var pwElt = q$('popupPwDlgPwd');
        pwElt.value = "";
        var errElt = q$('popupPwDlgError');
        errElt.innerHTML = QSTR.loginPasswordIncorrectText;
        Common.cshow(errElt);
        pwElt.focus();
    };
    return QCredentialsImpl;
}());
var gQCredentials = new QCredentialsImpl();

//include "XML.js"



// Password.js

var Password = (function () {
    function Password() {
    }
    Password._passwordChangedWeb = function (pwd, resultsTxt, urlOnSuccess) {
        var resultsXml = XML.CreateDocument(resultsTxt);
        var userid = '';
        if (resultsTxt.indexOf("NO_SUCH_USER") > -1 || resultsTxt.indexOf("NO_SUCH_TOKEN") > -1) {
            alert(QSTR.passwordNotChanged);
            return;
        }
        if (resultsXml.documentElement.getAttribute("type") === "result") {
            userid = resultsXml.documentElement.getAttribute("userid");
        }
        gQCredentials.AttemptLogin(userid, pwd, function (isOK) {
            if (isOK) {
                alert(QSTR.passwordChanged);
                if (urlOnSuccess) {
                    window.location.href = urlOnSuccess; // usually '/'
                }
                else {
                    createCookie("resumeAfterLogin", 'true', Common.ONE_MINUTE_IN_DAYS);
                    Common.attemptWindowQuit();
                    Common.quickReload();
                }
            }
            else {
                alert(QSTR.passwordNotChanged);
            }
        });
    };
    Password._passwordChangedMobile = function (pwd, results) {
        var authResults = XML.CreateDocument(results);
        var root = authResults.documentElement;
        var userid = root.getAttribute("userid");
        if (!userid) {
            Password._passwordNotChangedShared();
            return;
        }
        alert(QSTR.passwordChanged);
        document.location.href = "/";
    };
    Password._passwordNotChangedShared = function () {
        alert(QSTR.passwordNotChanged);
    };
    Password._submitResetPassword = function (fieldNameMap, successHandler, urlOnSuccess) {
        var email = q$(fieldNameMap.email).value;
        if (!email) {
            alert(QSTR.emailRequired);
            return;
        }
        var pwd = q$(fieldNameMap.password).value;
        var pwd2 = q$(fieldNameMap.password2).value;
        if (pwd !== pwd2) {
            alert(QSTR.profileNewPasswordsDontMatch);
            return;
        }
        if (pwd.length < Password.MinPwdLen) {
            alert(QSTR.registerPasswordTooShort);
            return;
        }
        var token = queryString("t");
        if (!token)
            token = readCookie("createpwdtoken");
        var xmlDocument = XML.CreateDocument("<change_password></change_password>");
        var element = xmlDocument.documentElement;
        element.setAttribute("id", email);
        element.setAttribute("password", pwd);
        element.setAttribute("token", token);
        var successWrap = function (text) {
            successHandler(pwd, text, urlOnSuccess);
        };
        Ajax.postAsXml(QSettings.postUrl(), xmlDocument, successWrap, Password._passwordNotChangedShared);
    };
    // external  methods
    Password.submitResetPasswordWeb = function () {
        var urlOnSuccess = "/";
        Password._submitResetPassword(Password.defaultResetFieldNames, Password._passwordChangedWeb, urlOnSuccess);
    };
    Password.submitResetPasswordModalDlgWeb = function () {
        var urlOnSuccess = null; // just reload current page
        Password._submitResetPassword(Password.modalResetFieldNames, Password._passwordChangedWeb, urlOnSuccess);
    };
    Password.submitResetPasswordMobile = function () {
        var urlOnSuccess = "/";
        Password._submitResetPassword(Password.defaultResetFieldNames, Password._passwordChangedMobile, urlOnSuccess);
    };
    // this used to be defined on server through QSTR.registerPasswordLength
    // (because it was different on different domains.  Now it is define HERE
    // for JS/TS.  There is probably a corresponding definition in Java code.
    Password.MinPwdLen = 6;
    Password.defaultResetFieldNames = {
        email: "email",
        password: "password",
        password2: "password2"
    };
    Password.modalResetFieldNames = {
        email: "modalPwdResetDlgEmail",
        password: "modalPwdResetDlgPassword",
        password2: "modalPwdResetDlgConfirmPassword"
    };
    // Request an email with link to reset password
    Password.submitForgotPassword = function () {
        var email = q$('forgotPasswordEmail').value;
        if (!email)
            return;
        var pstatus = q$('forgotPasswordStatus');
        var ematch = email.match(Common.validEmailAddressRegEx);
        if (!ematch) {
            pstatus.innerHTML = "<div class='error'>" + QSTR.enterValidEmailAddress + "</div>";
            Common.cshow(pstatus);
            return;
        }
        var updateStatus = function () {
            var statusElt = q$('forgotPasswordStatus');
            statusElt.className = "statusOK";
            statusElt.innerHTML =
                sprintf(QSTR.forgotPasswordSuccess, q$('forgotPasswordEmail').value);
            q$('forgotButton').setAttribute("style", "visibility: hidden;display: none;");
        };
        setTimeout(function () {
            var addr = q$('forgotPasswordEmail').value;
            var url = "/q-webclient/?cmd=sendpass&email=" + encodeURIComponent(addr);
            Ajax.post(url, "", "text/plain", updateStatus, Common.doNothing);
        }, 200);
    };
    return Password;
}());




// PasswordPrompt.js

/// <reference path="Ajax.d.ts" />
/// <reference path="mootools.d.ts" />
/// <reference path="Common.d.ts" />
var PasswordPrompt = (function () {
    function PasswordPrompt(pwDlgBaseName, successFunc, errorFunc) {
        this._onSuccessFunc = successFunc;
        this._onErrorFunc = errorFunc;
        this._pwDlgBaseName = pwDlgBaseName;
        this._pwdEltName = pwDlgBaseName + PasswordPrompt._PwdExt;
        this._errorEltName = pwDlgBaseName + PasswordPrompt._ErrorExt;
        var elt = q$(this._pwdEltName);
        if (elt)
            elt.onkeydown = this.checkEnterKey.bind(this);
    }
    PasswordPrompt.prototype.showDlg = function () {
        this.clearError();
        // hide scrollbars on page
        var b = q$(document.body);
        b.addClass("pwNoOverflow");
        var dlgElt = q$(this._pwDlgBaseName);
        dlgElt.removeClass("pwHidden");
        dlgElt.addClass("pwShown");
    };
    PasswordPrompt.prototype.hideDlg = function () {
        this.clearError();
        this.clearError();
        // hide scrollbars on page
        var b = q$(document.body);
        b.removeClass("pwNoOverflow");
        var dlgElt = q$(this._pwDlgBaseName);
        dlgElt.removeClass("pwShown");
        dlgElt.addClass("pwHidden");
    };
    PasswordPrompt.prototype.checkPassword = function () {
        var pwElt = q$(this._pwdEltName);
        var pwd = pwElt.value;
        PasswordPrompt.checkPasswordExt(pwd, this._onSuccessFunc, this._onErrorFunc);
    };
    // static checkPasswordExt can be used by code that doesn't use or extend PasswordPrompt class
    PasswordPrompt.checkPasswordExt = function (pw, onSuccessFunc, onErrorFunc) {
        var xmlAuth = XML.CreateDocument("<checkPassword></checkPassword>");
        var pwelt = xmlAuth.documentElement;
        pwelt.setAttribute("pwd", pw);
        Ajax.postAsXml(QSettings.postUrl(), xmlAuth, function (resp) {
            var respDoc = XML.CreateDocument(resp);
            var type = respDoc.documentElement.getAttribute("type");
            if (type == 'success') {
                onSuccessFunc(respDoc);
            }
            else {
                onErrorFunc();
            }
        }, function (results) {
            onErrorFunc();
        });
    };
    PasswordPrompt.prototype.showError = function () {
        var eb = q$(this._errorEltName);
        Common.cshow(eb);
        eb.innerHTML = QSTR.loginPasswordIncorrectText;
    };
    PasswordPrompt.prototype.clearError = function () {
        var eb = q$(this._errorEltName);
        Common.chide(eb);
        eb.innerHTML = "";
    };
    PasswordPrompt.prototype.checkEnterKey = function (e) {
        // did they hit the enter key?
        var keynum = Common.keynumForEvent(e);
        if (keynum == 13) {
            this.checkPassword();
        }
    };
    PasswordPrompt._PwdExt = "Pwd";
    PasswordPrompt._ErrorExt = "Error";
    return PasswordPrompt;
}());




// DefaultText.js

var DefaultText = (function () {
    function DefaultText() {
    }
    DefaultText.onStartup = function () {
        setTimeout(DefaultText.addTextChangeFunctions, 1);
        return true;
    };
    DefaultText.addTextChangeFunctions = function () {
        var defaultTextItems = $$('.defaultText');
        for (var i = 0; i < defaultTextItems.length; i++) {
            DefaultText.addDefaultTextFunction(defaultTextItems[i]);
        }
        var fieldTippableItems = $$('.fieldTippable');
        for (var i = 0; i < fieldTippableItems.length; i++) {
            DefaultText.addFieldTipFunction(fieldTippableItems[i]);
        }
    };
    /* currently only used by this class
     * Returns a string or null
     */
    DefaultText.getExtraAttribute = function (e, attributeName) {
        if (e[attributeName] !== undefined) {
            return e[attributeName];
        }
        if (e.attributes[attributeName] !== undefined) {
            return e.attributes[attributeName].value;
        }
        return null;
    };
    // only used by this class
    DefaultText.addDefaultTextFunction = function (e) {
        if (e.hasAddedDefaultText) {
            return;
        }
        e.hasAddedDefaultText = true;
        var defaultText = DefaultText.getExtraAttribute(e, "defaultText");
        if (defaultText === null) {
            q$(e).removeClass('hasDefaultText');
            return;
        }
        // alert(defaultText); // alert out the defaultText
        var alternateElement = null;
        if (DefaultText.getExtraAttribute(e, "alternateID") !== null) {
            var alternateID = DefaultText.getExtraAttribute(e, "alternateID");
            alternateElement = q$(alternateID);
        }
        e.getValue = function () {
            if (e.value === defaultText) {
                return "";
            }
            return e.value;
        };
        e._fakeBlur = function () {
            if (e.value === "") {
                if (alternateElement !== null) {
                    Common.cshow(alternateElement);
                    Common.chide(e);
                }
                else {
                    if (e.nodeName.toUpperCase() != "SELECT") {
                        e.value = defaultText;
                    }
                    q$(e).addClass("hasDefaultText");
                    if (e.id == 'qSearchRequest' || q$(e).hasClass("defaultColor"))
                        q$(e).addClass("hasDefaultColor");
                }
            }
        };
        q$(e).addEvent('blur', e._fakeBlur);
        q$(e).addEvent('focus', function () {
            // we want to remove all instances of the default text in the current
            // value of the textbox. Unfortunately, Javascript doesn't have a
            // straight
            // "replace" method - it only takes a regular expression. So we have to
            // pre-process the default text to escape it, then do a regular express
            // replacement
            var defaultTextPattern = defaultText.replace(/[\W]/g, function (m) {
                return "\\" + m;
            });
            if (e.nodeName.toUpperCase() == "SELECT") {
                defaultTextPattern = '';
            }
            var pattern = new RegExp(defaultTextPattern);
            var v = e.value;
            if (pattern.test(v)) {
                e.value = v.replace(pattern, '');
                q$(e).removeClass("hasDefaultText");
                if (e.id == 'qSearchRequest' || q$(e).hasClass("defaultColor"))
                    q$(e).removeClass("hasDefaultColor");
            }
            if (e.type === "password") {
                e.select();
            }
        });
        if (alternateElement !== null) {
            var altelt_1 = q$(alternateElement);
            altelt_1.onfocus = function () {
                Common.chide(altelt_1);
                Common.cshow(e);
                q$(e).focus();
            };
            Common.chide(e);
            Common.cshow(altelt_1);
            altelt_1.addClass('hasDefaultText');
            altelt_1.value = defaultText;
            altelt_1.disabled = false;
        }
        else {
            // if we reload the page - the textboxes will start with the default text...
            // so we need to dim it out
            if ((e.value === "") || (e.value === defaultText)) {
                q$(e).addClass("hasDefaultText");
                e.value = defaultText;
                if (e.id == 'qSearchRequest' || q$(e).hasClass("defaultColor"))
                    q$(e).addClass("hasDefaultColor");
            }
        }
        /*
         * It's now late enough in the page loading process that we can re-enable
         * input
         */
        var elt = q$(e);
        elt.disabled = false;
    };
    DefaultText.addFieldTipFunction = function (e) {
        var fieldTipID = DefaultText.getExtraAttribute(e, "fieldTipID");
        var fieldTipValueID = DefaultText.getExtraAttribute(e, "fieldTipValueID");
        if ((q$(fieldTipID) === null) || (q$(fieldTipValueID) === null)) {
            return;
        }
        q$(e).addEvent('blur', function () {
            var fldelt = q$(fieldTipID);
            fldelt.inUse = false;
            setTimeout(function () {
                if (fldelt.inUse === false) {
                    fldelt.setStyle('left', "-500px");
                }
            }, 250);
        });
        q$(e).addEvent('focus', function () {
            var fldelt = q$(fieldTipID);
            fldelt.inUse = true;
            var eelt = q$(e);
            $$("#" + fieldTipID + " .innerBody").forEach(function (innerBody) {
                innerBody.innerHTML = q$(fieldTipValueID).innerHTML;
            });
            fldelt.setStyle('top', (eelt.getPosition().y - 10) + "px");
            fldelt.setStyle('left', (eelt.getPosition().x - fldelt.getSize().x + 8) + "px");
        });
    };
    return DefaultText;
}());
doOnPageReady(DefaultText.onStartup);




// MessageList.js

//xnclude "DefaultText.js"
//xnclude "CommonWeb.js"
/// <reference path="Common.d.ts" />
/// <reference path="Mootools.d.ts" />
/// <reference path="Common.d.ts" />
/*********************************************************************************************************
 * Javascript Support for CarouselRenderer
 *********************************************************************************************************/
var Carousel = (function () {
    function Carousel(options) {
        this._items = [];
        this._numItems = 0;
        this._itemWidth = 297;
        this._currentLeftMostItem = 0;
        this.rightArrow = null;
        this.leftArrow = null;
        this._itemIdentifier = options.itemIdentifier;
        if (options.slidesPerClick) {
            this._slidesPerClick = options.slidesPerClick;
        }
        else {
            this._slidesPerClick = 3;
        }
        this._items = [];
        this._numItems = 0;
        this._itemWidth = 297;
        this._currentLeftMostItem = 0;
    }
    Carousel.prototype.Prepare = function () {
        var tempThis = this;
        var container = q$('carousel_contents_' + this._itemIdentifier);
        var lastElem;
        $$('#carousel_contents_' + this._itemIdentifier + ' .carouselItem').each(function (e) {
            tempThis._items.push(e);
            tempThis._numItems++;
            lastElem = e;
        });
        container.setStyle('width', this._numItems * this._itemWidth);
        this.rightArrow = q$('carousel_right_' + this._itemIdentifier);
        if (this.rightArrow) {
            this.rightArrow.onclick = function () { tempThis.Scroll(1); };
            HoverStates.addHoverFunction(this.rightArrow, 'hoverItem', 'hoverItem');
        }
        this.leftArrow = q$('carousel_left_' + this._itemIdentifier);
        if (this.leftArrow) {
            this.leftArrow.onclick = function () { tempThis.Scroll(-1); };
            HoverStates.addHoverFunction(this.leftArrow, 'hoverItem', 'hoverItem');
        }
        this.Scroll(0);
    };
    Carousel.prototype.Scroll = function (delta) {
        delta = delta * this._slidesPerClick;
        var nextLeftMostItem = this._currentLeftMostItem + delta;
        if (nextLeftMostItem < 0) {
            nextLeftMostItem = 0;
        }
        if (this.leftArrow) {
            this.leftArrow.toggleClass('disabled', (nextLeftMostItem <= 0));
        }
        var maxLeftMost = this._numItems - 3;
        if (nextLeftMostItem >= maxLeftMost) {
            nextLeftMostItem = maxLeftMost;
        }
        if (this.rightArrow) {
            this.rightArrow.toggleClass('disabled', (nextLeftMostItem >= maxLeftMost));
        }
        if (nextLeftMostItem < 0 || nextLeftMostItem > maxLeftMost) {
            return;
        }
        var desiredMarginLeft = -(this._itemWidth * nextLeftMostItem);
        var container = q$('carousel_contents_' + this._itemIdentifier);
        var fx = new Fx.Tween(q$(container), {
            duration: 500,
            transition: Fx.Transitions.Quad.easeInOut,
            onComplete: function () { }
        });
        this._currentLeftMostItem = nextLeftMostItem;
        //this._currentRightMostItem = nextLeftMostItem+2;
        fx.start('margin-left', desiredMarginLeft + 'px');
    };
    return Carousel;
}());

//include "DefaultText.js"
//include "CommonWeb.js"



// ReferralQmd.js

/// <reference path="ReferralLink.ts" />
/// <reference path="../js/df/IDataform.d.ts" />
/// <reference path="Common.d.ts" />
var ReferralQmd = (function () {
    function ReferralQmd() {
    }
    ReferralQmd.onLoaded = function () {
        if (typeof QModalDialog != 'undefined') {
            if (typeof Referparams !== 'undefined' && Referparams !== null) {
                ReferralQmd.referDialog = new QModalDialog(q$('referOptionsContainer'), Referparams.referPresentation);
            }
        }
    };
    ReferralQmd.referDialog = null;
    return ReferralQmd;
}());
AfterStartupEvents.registerAfterStartup(ReferralQmd.onLoaded);
function toggleRefer(forceToTop) {
    if (ReferralQmd.referDialog) {
        setupReferral();
        referral.show('referDialog');
    }
}
function setupReferral() {
    if (!Referparams) {
        Common.log("ERROR ReferralQmd.Referparams: not defined");
        return;
    }
    if (gQCredentials.isLoginLimited()) {
        gQCredentials.launchPasswordDlg(true);
        return false;
    }
    var title = Referparams.referralTitle || document.title;
    referral.setReferralTitle(title);
    if (Referparams.referralURI) {
        referral.setReferralURI(Referparams.referralURI);
    }
    referral.setEmailTemplate(Referparams.emailTemplate);
    referral.setEmailBody(Referparams.emailBody);
    q$('referOptionsContainer').toggleClass('referOptionsContainerNonLatin', !Referparams.supportsMailTo);
    referral.setSupportsMailTo(Referparams.supportsMailTo);
    referral.setReferralDfid(Referparams.ReferralDfid);
    try {
        var df = Common.currentDfInPlayer();
        if (df) {
            df.referClicked("mail");
        }
    }
    catch (e) {
    }
    return true;
}
function setupPageReferral() {
    if (gQCredentials.isLoginLimited()) {
        gQCredentials.launchPasswordDlg(true);
        return false;
    }
    var title = Referparams.referralTitle || document.title;
    referral.setReferralTitle(title);
    if (Referparams.referralURI) {
        referral.setReferralURI(Referparams.referralURI);
    }
    referral.setEmailTemplate(Referparams.emailTemplate);
    referral.setEmailBody(Referparams.emailBody);
    q$('referOptionsContainer').toggleClass('referOptionsContainerNonLatin', !Referparams.supportsMailTo);
    referral.setSupportsMailTo(Referparams.supportsMailTo);
    referral.setReferralDfid(Referparams.ReferralDfid);
    try {
        var df = Common.currentDfInPlayer();
        if (df) {
            df.referClicked("mail");
        }
    }
    catch (e) {
    }
    return true;
}
function referViaEmail() {
    if (setupReferral())
        referral.show();
    return false;
}
function referViaClipboard() {
    if (!Referparams) {
        Common.log("ERROR ReferralQmd.Referparams: not defined");
        return;
    }
    if (gQCredentials.isLoginLimited()) {
        gQCredentials.launchPasswordDlg(true);
        return;
    }
    var href = Referparams.referViaClipboard + "?link=" + encodeURIComponent(Referparams.clipBoardLink);
    var height = 255;
    var b = q$(document.body);
    if (b.hasClass('chrome'))
        height = 255;
    if (b.hasClass('msie'))
        height = 240;
    window.open(href, 'clipboard', 'width=500,height=' + height + ',resizable=yes,scrollbars=no,location=no,toolbar=no,status=no,menubar=no');
    // not all fmt do this needs work jjm ???
    try {
        var df = Common.currentDfInPlayer();
        if (df) {
            df.referClicked("clipboard");
        }
    }
    catch (e) {
    }
}
function referToFacebook() {
    if (!Referparams) {
        Common.log("ERROR ReferralQmd.Referparams: not defined");
        return;
    }
    if (gQCredentials.isLoginLimited()) {
        gQCredentials.launchPasswordDlg(true);
        return;
    }
    var host = location.host;
    var referTitle = (Referparams.referralTitle) ? Referparams.referralTitle : document.title;
    if (host.indexOf("secure.") == 0)
        host = host.substr(7);
    var href = "https://www.facebook.com/sharer.php?u=" +
        encodeURIComponent(Referparams.fblink) +
        "&t="
        + encodeURIComponent(referTitle)
        + "&src=sp";
    Common.openWindow(href, 'facebook', 'width=750,height=400,resizable=yes,scrollbars=no,location=yes,toolbar=no,status=no,menubar=no');
    try {
        var df = Common.currentDfInPlayer();
        if (df) {
            df.referClicked("facebook");
        }
    }
    catch (e) {
    }
}
function referToLinkedIn() {
    if (!Referparams) {
        Common.log("ERROR ReferralQmd.Referparams: not defined");
        return;
    }
    if (gQCredentials.isLoginLimited()) {
        gQCredentials.launchPasswordDlg(true);
        return;
    }
    var host = location.host;
    if (host.indexOf("secure.") == 0)
        host = host.substr(7);
    var link = Referparams.lilink;
    var referTitle = (Referparams.referralTitle) ? Referparams.referralTitle : document.title;
    var href = "http://www.linkedin.com/shareArticle?mini=true&url=" +
        encodeURIComponent(link) +
        "&title=" +
        encodeURIComponent(referTitle) +
        "&source=Quantia+Communications&summary=" + encodeURIComponent(Referparams.description);
    Common.openWindow(href, 'linkedin', 'width=520,height=380,resizable=yes,scrollbars=no,location=yes,toolbar=no,status=no,menubar=no');
    try {
        var df = Common.currentDfInPlayer();
        if (df) {
            df.referClicked("linkedin");
        }
    }
    catch (e) {
    }
}




// AjaxWeb.js

/**
 * (c) 2014 Quantia, Inc.
 * Created by david.barbrow on 12/12/2014.
 */
///<reference path="Ajax.d.ts"/>
///<reference path="Window.d.ts"/>
var AjaxWeb = (function () {
    function AjaxWeb() {
        this._factory = null;
        this._requestList = [];
        this._retryCount = 0;
    }
    AjaxWeb.prototype.createRequest = function () {
        var request = null;
        if (!this._factory) {
            for (var i = 0; i < AjaxWeb._factories.length; i++) {
                try {
                    var factory = AjaxWeb._factories[i];
                    request = factory();
                    if (request) {
                        this._factory = factory;
                        break;
                    }
                }
                catch (e) {
                }
            }
        }
        else {
            request = this._factory();
        }
        if (request) {
            if (this._requestList) {
                this._requestList.push(request);
            }
            return (request);
        }
        else {
            // alert("Error creating request object!");
            return (null);
        }
    };
    AjaxWeb.prototype.cleanUpRequests = function () {
        for (var i = 0; i < this._requestList.length; i++) {
            try {
                this._requestList[i].onreadystatechange = null;
                if (typeof cleanUp !== 'undefined') {
                    cleanUp(this._requestList[i]);
                }
            }
            catch (e) {
                return;
            }
        }
    };
    AjaxWeb.prototype.getText = function (url, onSuccess, onFailure) {
        var request = this.createRequest();
        request.onreadystatechange = function () {
            if (request && request.readyState == 4) {
                try {
                    if (request.status < 400) {
                        if (onSuccess)
                            onSuccess(request.responseText);
                    }
                    else if (request) {
                        if (onFailure)
                            onFailure(request.responseText);
                    }
                }
                catch (e) { }
                request = null;
            }
        };
        request.open("GET", url, true);
        request.setRequestHeader('If-Modified-Since', 'Mon, 26 Jul 1997 05:00:00 GMT');
        request.send(null);
        return request;
    };
    AjaxWeb.prototype.getTextPreferringCache = function (url, onSuccess, onFailure) {
        var request = this.createRequest();
        request.onreadystatechange = function () {
            if (request && request.readyState == 4) {
                try {
                    if (request.status < 400) {
                        if (onSuccess)
                            onSuccess(request.responseText);
                    }
                    else if (request) {
                        if (onFailure)
                            onFailure(request.responseText);
                    }
                }
                catch (e) { }
                request = null;
            }
        };
        request.open("GET", url, true);
        request.setRequestHeader('Cache-Control', 'max-age=86400'); // in the last day is good enough
        request.send(null);
        return request;
    };
    AjaxWeb.prototype.getHTML5AudioPreferringCache = function (url, onSuccess, onFailure) {
        var request = this.createRequest();
        request.responseType = "blob";
        request.onreadystatechange = function () {
            if (request && request.readyState == 4) {
                try {
                    if (request.status < 400) {
                        if (onSuccess)
                            onSuccess(request.response); //xhr.response is now a blob object
                    }
                    else if (request) {
                        if (onFailure)
                            onFailure(request.responseText);
                    }
                }
                catch (e) { }
                request = null;
            }
        };
        request.open("GET", url, true);
        request.setRequestHeader('Cache-Control', 'max-age=86400'); // in the last day is good enough
        request.send(null);
        return request;
    };
    AjaxWeb.prototype.getXml = function (url, onSuccess, onFailure) {
        var request = this.createRequest();
        request.onreadystatechange = function () {
            try {
                if (request.readyState == 4) {
                    if ((request.status == 200 || request.status === 0)) {
                        if (onSuccess) {
                            if (!request.responseXML) {
                                var xmldoc = XML.CreateDocument(request.responseText);
                                onSuccess(xmldoc, request.responseText);
                            }
                            else {
                                onSuccess(request.responseXML, request.responseText);
                            }
                        }
                        request = null;
                    }
                    else if (request.status == 304) {
                        // NOT MODIfIED? pretend it is empty
                        if (onSuccess) {
                            var pseudoResponse = "<notModified></notModified>";
                            var xmldoc = XML.CreateDocument(pseudoResponse);
                            onSuccess(xmldoc, pseudoResponse);
                        }
                    }
                    else {
                        if (onFailure)
                            onFailure(request.status);
                    }
                }
            }
            catch (e) {
                if (onFailure)
                    onFailure(e);
            }
        };
        try {
            request.onerror = function () {
                if (onFailure)
                    onFailure();
            };
        }
        catch (e) { }
        request.open("GET", url, true);
        request.setRequestHeader('If-Modified-Since', 'Mon, 26 Jul 1997 05:00:00 GMT');
        request.send(null);
        return request;
    };
    AjaxWeb.prototype.getJSON = function (url, onSuccess, onFailure) {
        var request = this.createRequest();
        request.onreadystatechange = function () {
            try {
                if (request.readyState == 4) {
                    if ((request.status == 200 || request.status === 0)) {
                        if (onSuccess) {
                            var obj = JSON.decode(request.responseText);
                            onSuccess(obj, request.responseText);
                        }
                        request = null;
                    }
                    else {
                        if (onFailure)
                            onFailure(request.status);
                    }
                }
            }
            catch (e) {
                if (onFailure)
                    onFailure(e);
            }
        };
        try {
            request.onerror = function () {
                if (onFailure)
                    onFailure();
            };
        }
        catch (e) { }
        request.open("GET", url, true);
        request.send(null);
        return request;
    };
    AjaxWeb.prototype.getOldRequests = function () {
        return this._requestList;
    };
    // These perform posts but do not wait for a result
    // They return true or false based on whether the post succeeded to enqueue at all
    AjaxWeb.prototype.queueToServer = function (url, postBody, contentType) {
        try {
            if (!contentType)
                contentType = 'text/plain';
            var request = this.createRequest();
            request.open("POST", url, true);
            request.setRequestHeader("Content-Type", contentType);
            request.send(postBody);
            return true;
        }
        catch (e) {
            return false;
        }
    };
    AjaxWeb.prototype.queueXmlToServer = function (url, xmlDoc) {
        try {
            var strPostInfo = XML.serialize(xmlDoc);
            var request = this.createRequest();
            request.open("POST", url, true);
            request.setRequestHeader("Content-Type", "text/xml");
            request.send(strPostInfo);
            return true;
        }
        catch (e) {
            return false;
        }
    };
    // These perform posts asynchronously, and invoke their callbacks only when the server
    // responds or an error occurs
    AjaxWeb.prototype.post = function (url, postBody, contentType, onSuccess, onFailure) {
        var request = this.createRequest();
        request.onreadystatechange = function () {
            if (request && request.readyState == 4) {
                try {
                    if (request.status == 200) {
                        if (onSuccess) {
                            onSuccess(request.responseText);
                        }
                        request = null;
                    }
                    else {
                        if (onFailure) {
                            onFailure(request.status, request.statusText);
                        }
                        request = null;
                    }
                }
                catch (e) {
                    if (onFailure) {
                        onFailure();
                    }
                }
            }
        };
        request.open("POST", url, true);
        if (contentType) {
            request.setRequestHeader("Content-Type", contentType);
        }
        request.send(postBody);
    };
    AjaxWeb.prototype.postAsXml = function (url, xmlDoc, onSuccess, onFailure) {
        var strPostInfo = XML.serialize(xmlDoc);
        var request = this.createRequest();
        request.onreadystatechange = function () {
            if (request.readyState == 4) {
                if (request.status == 200) {
                    if (onSuccess)
                        onSuccess(request.responseText);
                    request = null;
                }
                else {
                    if (onFailure)
                        onFailure(request.status, request.statusText);
                    request = null;
                }
            }
        };
        request.open("POST", url, true);
        request.setRequestHeader("Content-Type", "text/xml");
        request.send(strPostInfo);
    };
    AjaxWeb.prototype.postXmlFromUnloadHandler = function (url, xmlDoc) {
        var strPostInfo = XML.serialize(xmlDoc);
        var request = this.createRequest();
        request.open("POST", url, false);
        request.setRequestHeader("Content-Type", "text/xml");
        request.send(strPostInfo);
    };
    // Array of functions each returning an XMLHttpRequest object
    AjaxWeb._factories = [
        function () { return new XMLHttpRequest(); },
        function () { return new ActiveXObject("Msxml3.XMLHTTP"); },
        function () { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); },
        function () { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); },
        function () { return new ActiveXObject("Msxml2.XMLHTTP"); },
        function () { return new ActiveXObject("Microsoft.XMLHTTP"); }
    ];
    return AjaxWeb;
}());
if (!PageFlavor.expectsMobileAjax())
    window.Ajax = new AjaxWeb();
window.addEvent('unload', function () {
    var ajaxWeb = Ajax;
    if (ajaxWeb._requestList) {
        ajaxWeb.cleanUpRequests();
    }
});




// PageHeader.js

doOnPageReady(function () {
    PageHeader.setup();
});
window.addEvent('beforeunload', function () {
    PageHeader.disableMenuEvents(5000);
    try {
        PageHeader.closeAllMenus();
    }
    catch (e) { }
});
var PageHeader = {};
PageHeader.createMouseEvent = function (i, isHovering, delay) {
    return function () {
        PageHeader.isHovering[i] = isHovering;
        PageHeader.prepareToUpdatePageHeader(delay);
    };
};
PageHeader.setup = function () {
    PageHeader.initSearchButton();
    PageHeader.initLanguageSelector();
    PageHeader.SHOW_DELAY_IN_MILLISECONDS = 350;
    PageHeader.HIDE_ACCOUNT_MENU_DELAY_IN_MILLISECONDS = 600;
    PageHeader.HIDE_DELAY_IN_MILLISECONDS = 200;
    PageHeader.CLICK_DELAY_IN_MILLISECONDS = 10;
    PageHeader.alertTimeouts = {};
    PageHeader.hasNotified = {};
    PageHeader.initAlert = function (command) {
        PageHeader.alertTimeouts[command] = null;
        PageHeader.hasNotified[command] = false;
    };
    PageHeader.notifyAlertViewed = function (command, element) {
        if (PageHeader.hasNotified[command])
            return;
        var url = QSettings.buildUrlCmd(command);
        url = url + "&alertViewedTimestamp=" + DateUtils.msNow();
        Ajax.getXml(url);
        PageHeader.hasNotified[command] = true;
        Array.each(element.getElements('.active'), function (e) {
            var id = 'alertNumberContainer_' + element.id;
            Common.chide(id);
        });
    };
    var createAlertEvent = function (command, element) {
        return function () {
            PageHeader.notifyAlertViewed(command, element);
        };
    };
    var createAlertMouseEnter = function (command, element) {
        return function () {
            if (!PageHeader.alertTimeouts[command]) {
                PageHeader.alertTimeouts[command] = setTimeout(function () {
                    PageHeader.notifyAlertViewed(command, element);
                    PageHeader.alertTimeouts[command] = null;
                }, 3000);
            }
        };
    };
    var createAlertMouseLeave = function (command) {
        return function () {
            var tmout = PageHeader.alertTimeouts[command];
            if (tmout) {
                clearTimeout(tmout);
                PageHeader.alertTimeouts[command] = null;
            }
        };
    };
    var addHoverableItem = function (inID, inFadeTime, targetItem, visClass, hiddenClass) {
        var item = {
            itemId: inID,
            isOpen: false,
            fadeTime: inFadeTime,
            itemToShowOrHideId: targetItem,
            visibleCssClass: visClass,
            hiddenCssClass: hiddenClass,
            hideDelay: PageHeader.HIDE_DELAY_IN_MILLISECONDS
        };
        PageHeader.hoverableItems.push(item);
    };
    var pointsAlertMenuElt = q$('pointsAlertMenu');
    var discAlertMenuElt = q$('discussionsAlertMenu');
    var intAlterMenuElt = q$('interestsAlertMenu');
    if (pointsAlertMenuElt) {
        PageHeader.initAlert('notifyqpointalertviewed');
        pointsAlertMenuElt.addEvent('click', createAlertEvent('notifyqpointalertviewed', pointsAlertMenuElt));
        pointsAlertMenuElt.addEvent('mouseenter', createAlertMouseEnter('notifyqpointalertviewed', pointsAlertMenuElt));
        pointsAlertMenuElt.addEvent('mouseleave', createAlertMouseLeave('notifyqpointalertviewed'));
    }
    if (discAlertMenuElt) {
        PageHeader.initAlert('notifydiscussionalertviewed');
        discAlertMenuElt.addEvent('click', createAlertEvent('notifydiscussionalertviewed', discAlertMenuElt));
        discAlertMenuElt.addEvent('mouseenter', createAlertMouseEnter('notifydiscussionalertviewed', discAlertMenuElt));
        discAlertMenuElt.addEvent('mouseleave', createAlertMouseLeave('notifydiscussionalertviewed'));
    }
    if (intAlterMenuElt) {
        PageHeader.initAlert('notifyinterestalertviewed');
        intAlterMenuElt.addEvent('click', createAlertEvent('notifyinterestalertviewed', intAlterMenuElt));
        intAlterMenuElt.addEvent('mouseenter', createAlertMouseEnter('notifyinterestalertviewed', intAlterMenuElt));
        intAlterMenuElt.addEvent('mouseleave', createAlertMouseLeave('notifyinterestalertviewed'));
    }
    PageHeader.hoverableItems = [];
    var visClsMegaMenu = ".visibleMegaMenuDropDown";
    var hidClsMegaMenu = ".hiddenMegaMenuDropDown";
    var visClsAcct = ".visibleAccountMenuDropDown";
    var hidClsAcct = ".hiddenAccountMenuDropDown";
    var visClsAlert = ".visibleAlertMenuDropDown";
    var hidClsAlert = ".hiddenAlertMenuDropDown";
    addHoverableItem("megaMenu", 250, "megaMenuDropDown", visClsMegaMenu, hidClsMegaMenu);
    addHoverableItem("accountMenu", 0, "accountMenuDropDown", visClsAcct, hidClsAcct);
    addHoverableItem("pointsAlertMenu", 0, "pointsAlertMenuDropDown", visClsAlert, hidClsAlert);
    addHoverableItem("discussionsAlertMenu", 0, "discussionsAlertMenuDropDown", visClsAlert, hidClsAlert);
    addHoverableItem("interestsAlertMenu", 0, "interestsAlertMenuDropDown", visClsAlert, hidClsAlert);
    addHoverableItem("pointsAlertMenu", 0, "alertNotch_pointsAlertMenu", visClsAlert, hidClsAlert);
    addHoverableItem("discussionsAlertMenu", 0, "alertNotch_discussionsAlertMenu", visClsAlert, hidClsAlert);
    addHoverableItem("interestsAlertMenu", 0, "alertNotch_interestsAlertMenu", visClsAlert, hidClsAlert);
    PageHeader.isHovering = [];
    PageHeader.animations = [];
    for (var i = 0; i < PageHeader.hoverableItems.length; i++) {
        var hoverable = PageHeader.hoverableItems[i];
        var itemId = hoverable.itemId;
        PageHeader.isHovering[i] = false;
        if (q$(itemId)) {
            q$(itemId).addEvent('mouseenter', PageHeader.createMouseEvent(i, true, PageHeader.SHOW_DELAY_IN_MILLISECONDS));
            q$(itemId).addEvent('mouseleave', PageHeader.createMouseEvent(i, false, PageHeader.hoverableItems[i].hideDelay));
            q$(itemId).addEvent('click', PageHeader.createMouseEvent(i, true, PageHeader.CLICK_DELAY_IN_MILLISECONDS));
        }
    }
    PageHeader.disableMenuEvents(500);
    $$(".menuTeaser .menuItem").each(function (item) {
        var itemElt = q$(item);
        itemElt.addEvent('mouseenter', function () {
            itemElt.addClass("loggedOutTeaserMenuItemHover");
        });
        itemElt.addEvent('mouseleave', function () {
            itemElt.removeClass("loggedOutTeaserMenuItemHover");
        });
    });
    $$('.menuTeaser').each(function (item) {
        var itemElt = q$(item);
        itemElt.addEvent('mouseenter', PageHeader.openMegaMenu);
        itemElt.addEvent('mouseleave', PageHeader.closeMegaMenu);
    });
    PageHeader.elementsThatAreHidden = [];
    PageHeader.addColumnTransitionEvents();
};
PageHeader.openMegaMenu = function () {
    PageHeader.isMegaMenuDisabled = true;
    PageHeader.prepareToUpdatePageHeader(PageHeader.HIDE_DELAY_IN_MILLISECONDS);
};
PageHeader.closeMegaMenu = function () {
    PageHeader.isMegaMenuDisabled = false;
    PageHeader.prepareToUpdatePageHeader(PageHeader.SHOW_DELAY_IN_MILLISECONDS);
};
PageHeader.addToHoverable = function (obj, showDelayInMillis, clickDelayInMillis) {
    PageHeader.hoverableItems.push(obj);
    var i = PageHeader.hoverableItems.length - 1;
    var itemId = PageHeader.hoverableItems[i].itemId;
    PageHeader.isHovering[i] = false;
    var elt = q$(itemId);
    if (elt) {
        elt.addEvent('mouseenter', PageHeader.createMouseEvent(i, true, showDelayInMillis));
        elt.addEvent('mouseleave', PageHeader.createMouseEvent(i, false, PageHeader.hoverableItems[i].hideDelay));
        elt.addEvent('click', PageHeader.createMouseEvent(i, true, clickDelayInMillis));
    }
};
PageHeader.initSearchButton = function () {
    var sr = q$('qSearchRequest');
    if (sr) {
        sr.addEvent('keyup', Common.searchRequest);
        sr.addEvent('mouseup', Common.searchMouseUp);
        sr.addEvent('mousemove', Common.searchMouseMove);
        sr.addEvent('mouseout', Common.searchMouseExit);
    }
};
PageHeader.initLanguageSelector = function () {
    var langSelElt = q$('languageSelector');
    if (!langSelElt)
        return;
    if (readCookie("languageConfirmed") != null)
        return;
    setTimeout(function () {
        Common.scrollToHeight(langSelElt, 32, 500, null);
        var qplayers = $$('.qplayerContainer');
        if (qplayers) {
            var qplayer = qplayers[0];
            if (qplayer) {
                var currentTop = qplayer.getCoordinates().top;
                qplayer.set('tween', { duration: 500, wait: false });
                qplayer.tween('top', currentTop + 32);
            }
        }
    }, 1000);
};
PageHeader.prepareToUpdatePageHeader = function (delay) {
    if (PageHeader.updateTimer) {
        clearTimeout(PageHeader.updateTimer);
    }
    PageHeader.updateTimer = setTimeout(PageHeader.updatePageHeader, delay);
};
PageHeader.forceSelectToClose = function (elem) {
    if (elem) {
        // remarkably, this has the effect of making a multiline selectbox contract to a closed state
        elem.size = elem.options.length;
        elem.size = 0;
    }
};
PageHeader.updatePageHeader = function () {
    if (!PageHeader.areMenuTransitionsEnabled)
        return;
    for (var i = 0; i < PageHeader.hoverableItems.length; i++) {
        var hoverableItem = PageHeader.hoverableItems[i];
        var olda = PageHeader.animations[i];
        if (olda) {
            olda.cancel();
            PageHeader.animations[i] = null;
        }
        var animation = new Fx.Morph(hoverableItem.itemToShowOrHideId, {
            duration: hoverableItem.fadeTime,
            transition: Fx.Transitions.Sine.easeOut
        });
        PageHeader.animations[i] = animation;
        if (!q$(hoverableItem.itemId)) {
            continue;
        }
        var openMenu = false;
        var closeMenu = false;
        if (PageHeader.isHovering[i]) {
            openMenu = true;
            if (hoverableItem.itemId == 'megaMenu' && PageHeader.isMegaMenuDisabled) {
                openMenu = false;
                if (hoverableItem.isOpen) {
                    closeMenu = true;
                }
            }
        }
        else {
            if (hoverableItem.isOpen) {
                closeMenu = true;
            }
        }
        if (openMenu) {
            q$(hoverableItem.itemToShowOrHideId).setStyle('visibility', 'visible');
            animation.start(hoverableItem.visibleCssClass);
            PageHeader.forceSelectToClose(q$('selectAction'));
            q$(hoverableItem.itemId).addClass("menuIsHovered");
            if (hoverableItem.itemId == 'accountMenu')
                q$('pageHeader').addClass("accountMenuIsOpen");
            hoverableItem.isOpen = true;
        }
        else if (closeMenu) {
            hoverableItem.isOpen = false;
            if (hoverableItem.itemId == 'accountMenu')
                q$('pageHeader').removeClass("accountMenuIsOpen");
            PageHeader.elementsThatAreHidden.each(function (item) {
                item.domElement.setStyle('opacity', item.originalOpacity);
            });
            animation.addEvent('complete', PageHeader.createCompletionHandler(q$(hoverableItem.itemToShowOrHideId)));
            animation.start(hoverableItem.hiddenCssClass);
            q$(hoverableItem.itemId).removeClass("menuIsHovered");
        }
    }
};
PageHeader.createCompletionHandler = function (itemElt) {
    return function () {
        itemElt.setStyle('visibility', 'hidden');
    };
};
PageHeader.disableMenuEvents = function (afterMouseMoveStartDelay) {
    PageHeader.areMenuTransitionsEnabled = false;
    var trackInitialMouseMovement = function () {
        setTimeout(function () {
            PageHeader.areMenuTransitionsEnabled = true;
            q$(document.body).removeEvent('mousemove', trackInitialMouseMovement);
        }, afterMouseMoveStartDelay);
    };
    q$(document.body).addEvent('mousemove', trackInitialMouseMovement);
};
PageHeader.closeAllMenus = function () {
    var elem, i;
    if (!PageHeader.hoverableItems)
        return;
    for (i = 0; i < PageHeader.hoverableItems.length; i++) {
        var hoverableItem = PageHeader.hoverableItems[i];
        PageHeader.isHovering[i] = false;
        if (PageHeader.animations[i] != null) {
            PageHeader.animations[i].cancel();
            PageHeader.animations[i] = null;
        }
        elem = q$(hoverableItem.itemToShowOrHideId);
        if (elem)
            new Fx.Morph(elem).set(hoverableItem.hiddenCssClass);
    }
};
PageHeader.addColumnTransitionEvents = function () {
    $$("#megaMenuHeader .menuItem").each(function (item) {
        q$(item).addEvent("mouseleave", function () {
            PageHeader.areMenuTransitionsEnabled = true;
            PageHeader.prepareToUpdatePageHeader(PageHeader.SHOW_DELAY_IN_MILLISECONDS);
        });
    });
};




// UrlInfo.js

var UrlInfo = (function () {
    function UrlInfo(q, completeUrl) {
        if (q.length > 1)
            this.q = q.substring(1, q.length);
        else
            this.q = null;
        this.keyValuePairs = [];
        if (this.q) {
            var qsplit = this.q.split("&");
            for (var i = 0; i < qsplit.length; i++) {
                this.keyValuePairs[i] = qsplit[i];
            }
        }
        this.pathParts = [];
        if (completeUrl) {
            var endIndex = completeUrl.indexOf("?");
            if (endIndex < 0)
                endIndex = completeUrl.indexOf("#");
            if (endIndex < 0)
                endIndex = completeUrl.length;
            var resource = completeUrl.substring(0, endIndex);
            // if we start with a slash... get rid of that
            if (resource.indexOf("/") == 0)
                resource = resource.substring(1, endIndex);
            this.pathParts = resource.split("/");
        }
    }
    UrlInfo.prototype.getValue = function (s) {
        for (var j = 0; j < this.keyValuePairs.length; j++) {
            if (this.keyValuePairs[j].split("=")[0] == s)
                return this.keyValuePairs[j].split("=")[1];
        }
        return null;
    };
    UrlInfo.prototype.getParts = function () {
        return this.pathParts;
    };
    UrlInfo.prototype.qsWithArgsRemoved2 = function (arg1ToRemove, arg2ToRemove) {
        var qs = "";
        var sep = "";
        for (var j = 0; j < this.keyValuePairs.length; j++) {
            var pairAry = this.keyValuePairs[j].split("=");
            if (pairAry[0] != arg1ToRemove && pairAry[0] != arg2ToRemove) {
                var pairStr = pairAry[0];
                if (pairAry.length > 1)
                    pairStr += ("=" + pairAry[1]);
                qs += (sep + pairStr);
                sep = "&";
            }
        }
        return qs;
    };
    UrlInfo.queryString = function (key) {
        var urlStuff = new UrlInfo(location.search);
        var result = urlStuff.getValue(key);
        if (!result) {
            return result;
        }
        return unescape(result);
    };
    return UrlInfo;
}());
// Warning!!!! There are other implementations of queryString().
queryString = function (key) {
    return UrlInfo.queryString(key);
};
var UrlBuilder = (function () {
    function UrlBuilder() {
        this._path = "";
        this._args = [];
        this._anchor = "";
        this._suffix = null;
    }
    UrlBuilder.init = function (path) {
        var u = new UrlBuilder();
        u.setPath(path);
        return u;
    };
    UrlBuilder.prototype.buildStr = function () {
        var url = "";
        if (this._scheme) {
            url = this._scheme;
            url += "://";
        }
        if (this._host) {
            url += this._host;
            url += "/";
        }
        url += this._path;
        var sep = "?";
        for (var i = 0; i < this._args.length; i++) {
            url += sep;
            url += this._args[i];
            sep = "&";
        }
        if (this._anchor) {
            url += "#";
            url += this._anchor;
        }
        if (this._suffix) {
            url += this._suffix;
        }
    };
    UrlBuilder.prototype.setScheme = function (s) {
        this._scheme = s;
    };
    UrlBuilder.prototype.setHost = function (h) {
        this._host = h;
    };
    UrlBuilder.prototype.setPath = function (p) {
        this._path = p;
    };
    UrlBuilder.prototype.addArg = function (n, v) {
        var arg = n;
        if (v)
            arg += "=" + v;
        this._args.push(arg);
    };
    UrlBuilder.prototype.setAnchor = function (a) {
        this._anchor = a;
    };
    UrlBuilder.prototype.setSSLSuffix = function () {
        this._suffix = ";ssl";
    };
    return UrlBuilder;
}());




// MemoryManagement.js

var MemoryManagement = (function () {
    function MemoryManagement() {
    }
    MemoryManagement.HoverItemsAdd = function (item) {
        MemoryManagement.HoverItems.push(item);
    };
    MemoryManagement.IsDefined = function (variable) {
        return (!(!(variable || false)));
    };
    MemoryManagement.CleanUpHoverItems = function () {
        for (var i = 0; i < MemoryManagement.HoverItems.length; i++) {
            var item = MemoryManagement.HoverItems[i];
            if (item) {
                item.onmouseover = null;
                item.onmouseout = null;
                item.onmousemove = null;
                item.onmouseenter = null;
                item.onmouseleave = null;
                item.onmousedown = null;
                item.onmouseup = null;
                item.onclick = null;
                item = null;
            }
        }
    };
    MemoryManagement.CleanUpOldRequests = function () {
        for (var i = 0; i < MemoryManagement.OldRequests.length; i++) {
            try {
                MemoryManagement.OldRequests[i].onreadystatechange = null;
                MemoryManagement.CleanUp(Ajax.getOldRequests());
            }
            catch (e) {
                return;
            }
        }
    };
    MemoryManagement.CleanUp = function (objList) {
        var obj;
        for (obj in objList) {
            if (!objList.hasOwnProperty(obj))
                continue;
            try {
                if (obj || obj.hasCleanedUp)
                    return;
                if (!MemoryManagement.IsDefined(obj.nodeType)) {
                    obj.hasCleanedUp = true;
                }
                for (var prop in obj) {
                    switch (typeof (obj[prop])) {
                        case "object":
                            if (!MemoryManagement.IsDefined(obj.nodeType)) {
                                if (obj[prop] != obj) {
                                    MemoryManagement.CleanUp(obj[prop]);
                                }
                                try {
                                    obj[prop] = null;
                                }
                                catch (e) {
                                }
                            }
                            break;
                        case "function":
                            if (!MemoryManagement.IsDefined(obj.nodeType)) {
                                obj[prop] = null;
                            }
                            break;
                    }
                }
            }
            catch (e) {
            }
        }
    };
    MemoryManagement.HoverItems = [];
    MemoryManagement.OldRequests = [];
    return MemoryManagement;
}());
window.addEvent('unload', function () {
    MemoryManagement.CleanUpHoverItems();
    MemoryManagement.CleanUpOldRequests();
});




// HoverStates.js

//xnclude "MemoryManagement.js"
/// <reference path="MemoryManagement.ts" />
var HoverStates = (function () {
    function HoverStates() {
    }
    HoverStates.addHoverFunctions = function (e) {
        if (!e)
            e = document.body;
        var theElt = q$(e);
        var hoverItems = theElt.getElements('.hoverable');
        for (var i = 0; i < hoverItems.length; i++)
            HoverStates.addHoverFunction(hoverItems[i], 'hoverItem', 'hoverItem');
        hoverItems = theElt.getElements('.mouseOverable');
        for (var i = 0; i < hoverItems.length; i++)
            HoverStates.addMouseOverFunction(hoverItems[i], 'mousedOver');
        hoverItems = theElt.getElements('.transparentButton, .overGrayButton');
        for (var i = 0; i < hoverItems.length; i++)
            HoverStates.addHoverFunction(hoverItems[i], 'onHoverButton', 'onActiveButton');
        hoverItems = theElt.getElements('.orangeButton');
        for (var i = 0; i < hoverItems.length; i++)
            HoverStates.addHoverFunction(hoverItems[i], 'onOrangeHoverButton', 'onOrangeActiveButton');
        hoverItems = theElt.getElements('.qBlueButtonLeft');
        for (var i = 0; i < hoverItems.length; i++)
            HoverStates.addHoverFunction(hoverItems[i], 'qBlueButtonHover', 'qBlueButtonActive');
        hoverItems = theElt.getElements('.qSmallRoundButtonLeft');
        for (var i = 0; i < hoverItems.length; i++)
            HoverStates.addHoverFunction(hoverItems[i], 'qSmallRoundButtonHover', 'qSmallRoundButtonActive');
        hoverItems = theElt.getElements('.qOrangeButtonLeft');
        for (var i = 0; i < hoverItems.length; i++)
            HoverStates.addHoverFunction(hoverItems[i], 'qOrangeButtonHover', 'qOrangeButtonActive');
    };
    HoverStates.addHoverFunction = function (element, cssClass, activeClass) {
        var theElt = q$(element);
        var children = theElt.getElements(".hoverChild");
        theElt.addEvent('mouseover', function () {
            theElt.addClass(cssClass);
        });
        theElt.addEvent('focus', function () {
            theElt.addClass(cssClass);
        });
        theElt.addEvent('blur', function () {
            theElt.removeClass(cssClass);
        });
        theElt.addEvent('mouseleave', function () {
            theElt.removeClass(cssClass);
            theElt.removeClass(activeClass);
        });
        theElt.addEvent('mousedown', function () {
            theElt.addClass(activeClass);
        });
        theElt.addEvent('mouseup', function () {
            theElt.removeClass(activeClass);
        });
        theElt.addEvent('focus', function () {
            theElt.removeClass(activeClass);
        });
        MemoryManagement.HoverItemsAdd(element);
        for (var i = 0; i < children.length; i++) {
            q$(children[i]).addEvent('mouseover', function () {
                theElt.addClass(cssClass);
            });
        }
    };
    HoverStates.addMouseOverFunction = function (element, cssClass) {
        var theElt = q$(element);
        var children = theElt.getElements(".hoverChild");
        element.fixMouseOvered = function () {
            if (element.mouseovered) {
                theElt.addClass(cssClass);
            }
            else {
                theElt.removeClass(cssClass);
            }
        };
        var onEnterFunction = function () {
            if (!element.mouseovered) {
                element.mouseovered = true;
                clearTimeout(element.mouseovertimeout);
                element.mouseovertimeout = setTimeout(element.fixMouseOvered, 250);
            }
        };
        var onLeaveFunction = function () {
            if (element.mouseovered) {
                element.mouseovered = false;
                clearTimeout(element.mouseovertimeout);
                element.mouseovertimeout = setTimeout(element.fixMouseOvered, 100);
            }
        };
        q$(element).addEvent('mouseover', onEnterFunction);
        q$(element).addEvent('mouseleave', onLeaveFunction);
        for (var i = 0; i < children.length; i++) {
            q$(children[i]).addEvent('mouseover', onEnterFunction);
        }
    };
    return HoverStates;
}());
doOnPageReady(function () {
    setTimeout(HoverStates.addHoverFunctions, 200);
    return false;
});

//include "MemoryManagement.js"



// Viewport.js

var Viewport = (function () {
    function Viewport() {
    }
    Viewport.windowWidth = function () {
        return (document.documentElement && document.documentElement.clientWidth) ||
            window.innerWidth ||
            self.innerWidth ||
            (document.body && document.body.clientWidth) ||
            3; // 3 inches
    };
    Viewport.windowHeight = function () {
        var h = 0;
        if (self.innerHeight) {
            // all except Explorer
            h = self.innerHeight;
        }
        else if (document.documentElement && document.documentElement.clientHeight) {
            // Explorer 6 Strict Mode
            h = document.documentElement.clientHeight;
        }
        else if (document.body) {
            // other Explorers
            h = document.body.clientHeight;
        }
        return (h || 4); // default of 4 inches
    };
    Viewport.scrollX = function () {
        if (self.pageYOffset)
            return self.pageXOffset;
        else if (document.documentElement && document.documentElement.scrollTop)
            // Explorer 6 Strict
            return document.documentElement.scrollLeft;
        else if (document.body)
            return document.body.scrollLeft;
    };
    Viewport.scrollY = function () {
        if (self.pageYOffset)
            return self.pageYOffset;
        else if (document.documentElement && document.documentElement.scrollTop)
            // Explorer 6 Strict
            return document.documentElement.scrollTop;
        else if (document.body)
            return document.body.scrollTop;
    };
    Viewport.pageWidth = function () {
        return (document.documentElement && document.documentElement.scrollWidth) ?
            document.documentElement.scrollWidth :
            (document.body.scrollWidth > document.body.offsetWidth) ?
                document.body.scrollWidth : document.body.offsetWidth;
    };
    Viewport.pageHeight = function () {
        return (document.documentElement && document.documentElement.scrollHeight) ?
            document.documentElement.scrollHeight :
            (document.body.scrollHeight > document.body.offsetHeight) ?
                document.body.scrollHeight : document.body.offsetHeight;
    };
    Viewport.scrollTo = function (y) {
        if (!Viewport._windowScroller) {
            q$(window).addEvent('mousewheel', Common.preventDefault);
            Viewport._windowScroller = new Fx.Scroll(window, { wait: false,
                duration: 500,
                transition: Fx.Transitions.Quad.easeInOut
            });
            Viewport._windowScroller.start(0, y);
            setTimeout(function () {
                Viewport._windowScroller = null;
                var w = q$(window);
                w.removeEvent('mousewheel', Common.preventDefault);
            }, 500);
        }
    };
    Viewport.isScrolling = function () {
        return !(!Viewport._windowScroller);
    };
    Viewport._windowScroller = null;
    return Viewport;
}());




// PopupPreview.js

//xnclude "MemoryManagement.js"
//xnclude "Viewport.js"
/////////////////////////////
// Popup Preview Stuff...////
/////////////////////////////
var PopupPreview = (function () {
    function PopupPreview() {
    }
    PopupPreview.initOnPageReady = function () {
        setTimeout(PopupPreview.Update, 200);
        return true;
    };
    PopupPreview.Update = function (e) {
        if (!(e)) {
            e = document.body;
        }
        // uncomment when this is ready
        var items = q$(e).getElements('.dataformPopupPreviewable');
        for (var i = 0; i < items.length; i++) {
            PopupPreview.Setup(items[i], PopupPreview.DATAFORM);
        }
        var authors = q$(e).getElements('.profilePopupPreviewable');
        for (var i = 0; i < authors.length; i++) {
            PopupPreview.Setup(authors[i], PopupPreview.PROFILE);
        }
    };
    PopupPreview.Setup = function (hoverItem, hoverType) {
        hoverItem.addEvent('mouseover', function (e) {
            PopupPreview.SetMouseLocation(e.page.x, e.page.y);
            PopupPreview.Hover(hoverItem.id, hoverItem, hoverType);
        });
        hoverItem.addEvent('mousemove', function (e) {
            PopupPreview.SetMouseLocation(e.page.x, e.page.y);
        });
        hoverItem.addEvent('mouseleave', PopupPreview.Leave);
        MemoryManagement.HoverItemsAdd(hoverItem);
    };
    PopupPreview.Hover = function (hoverId, element, hoverType) {
        if (q$('popupPreviewDataform') == null)
            return;
        if (PopupPreview.hoverId != hoverId) {
            PopupPreview.Leave();
            PopupPreview.hoverId = hoverId;
            PopupPreview.element = element;
            PopupPreview.timerControl = setTimeout(function () {
                PopupPreview.PostRequest(hoverId, hoverType);
            }, PopupPreview.REQUEST_DELAY);
        }
    };
    PopupPreview.SetMouseLocation = function (x, y) {
        PopupPreview.mouseX = x;
        PopupPreview.mouseY = y;
    };
    PopupPreview.PostRequest = function (hoverId, hoverType) {
        var pageName = "";
        var alternateElement = PopupPreview.element.getAttribute('popupid');
        if (alternateElement && q$(alternateElement)) {
            var text = q$(alternateElement).innerHTML;
            PopupPreview.Callback(text, hoverId);
        }
        else if ((PopupPreview.hoverId == hoverId) && hoverId != "0" && hoverId != "") {
            if (hoverType == PopupPreview.DATAFORM) {
                pageName = "/dataformPopup?dataformID=" + hoverId;
            }
            else if (hoverType == PopupPreview.REP) {
                pageName = "/repPopup?repID=" + hoverId;
            }
            else {
                pageName = "/profilePopup?authorID=" + hoverId;
            }
            Ajax.getText(pageName, function (text) {
                PopupPreview.Callback(text, hoverId);
            });
        }
    };
    ;
    PopupPreview.Callback = function (html, hoverId) {
        PopupPreview._previewContainer = q$('popupPreviewContainerDataform');
        PopupPreview._previewOuter = q$('popupPreviewDataform');
        if (PopupPreview.hoverId != hoverId)
            return;
        PopupPreview._previewContainer.innerHTML = html;
        PopupPreview._previewOuter.setStyle('left', '-1000px');
        Common.cshow(PopupPreview._previewOuter);
        // determine the proper place to put this popup preview thingy
        var width = PopupPreview._previewOuter.getSize().x;
        var height = PopupPreview._previewOuter.getSize().y;
        //var elementLeft = PopupPreview.element.getPosition().x;
        //var elementTop = PopupPreview.element.getPosition().y;
        //var elementWidth = PopupPreview.element.getSize().x;
        //var elementHeight = PopupPreview.element.getSize().y;
        var desiredLeft = PopupPreview.mouseX - (width * .8);
        var desiredTop = PopupPreview.mouseY - height - 40;
        /*
         * if (elementLeft - width + 25 < desiredLeft) { desiredLeft =
         * elementLeft - width + 25; }
         */
        /*
         * if (elementTop - height + 10 < desiredTop) { desiredTop = elementTop -
         * height + 10; }
         */
        if (desiredTop < Viewport.scrollY()) {
            desiredTop = PopupPreview.mouseY + 40;
            if (desiredTop + height > Viewport.scrollY() + Viewport.windowHeight()) {
                desiredTop = Viewport.scrollY() + Viewport.windowHeight() - height - 12;
            }
        }
        if (desiredLeft < Viewport.scrollX()) {
            desiredLeft = PopupPreview.mouseX + 40;
            if (desiredLeft + width > Viewport.scrollX() + Viewport.windowWidth()) {
                desiredLeft = Viewport.scrollX() + Viewport.windowWidth() - width - 40;
            }
        }
        // if we are going to collide with the mouse - try moving left or right
        if ((desiredLeft < PopupPreview.mouseX) && (desiredLeft + width > PopupPreview.mouseX) && (desiredTop < PopupPreview.mouseY)
            && (desiredTop + height > PopupPreview.mouseY)) {
            desiredLeft = PopupPreview.mouseX - width - 40;
            desiredTop = PopupPreview.mouseY - (height / 2);
            if (desiredTop < Viewport.scrollY()) {
                desiredTop = Viewport.scrollY();
            }
            else if (desiredTop + height > Viewport.scrollY() + Viewport.windowHeight()) {
                desiredTop = Viewport.scrollY() + Viewport.windowHeight() - height;
            }
            if (desiredLeft < Viewport.scrollX()) {
                desiredLeft = PopupPreview.mouseX + 40;
                if (desiredLeft + width > Viewport.scrollX() + Viewport.windowWidth()) {
                    desiredLeft = Viewport.scrollX() + Viewport.windowWidth() - width - 40;
                }
            }
            // do we STILL collide? if so... give up
            if ((desiredLeft < PopupPreview.mouseX) && (desiredLeft + width > PopupPreview.mouseX) && (desiredTop < PopupPreview.mouseY)
                && (desiredTop + height > PopupPreview.mouseY)) {
                Common.chide(PopupPreview._previewOuter);
                return;
            }
        }
        // we know where the main popup preview thing is going to go - now we
        // have to place our little arrow
        var arrowX = -200;
        var arrowY = 0;
        var arrowWidth = 0;
        var arrowHeight = 0;
        var arrowUrl = "";
        if (desiredTop + height < PopupPreview.mouseY) {
            // use a bottom arrow
            // 64x34
            arrowWidth = 64;
            arrowHeight = 34;
            arrowY = desiredTop + height - 6; // make sure we overlap
            if (desiredLeft + arrowWidth < PopupPreview.mouseX) {
                arrowX = PopupPreview.mouseX - arrowWidth;
                arrowUrl = "popup_preview_bottomright.png";
            }
            else {
                arrowX = desiredLeft;
                arrowUrl = "popup_preview_bottomleft.png";
            }
        }
        else if (desiredTop > PopupPreview.mouseY) {
            // 64x34
            arrowWidth = 64;
            arrowHeight = 34;
            arrowY = desiredTop - arrowHeight + 4; // make sure we overlap
            if (desiredLeft + arrowWidth < PopupPreview.mouseX) {
                arrowX = PopupPreview.mouseX - arrowWidth;
                arrowUrl = "popup_preview_topright.png";
            }
            else {
                arrowX = desiredLeft;
                arrowUrl = "popup_preview_topleft.png";
            }
        }
        else if (desiredLeft + width < PopupPreview.mouseX) {
            // 34x64
            arrowWidth = 34;
            arrowHeight = 64;
            arrowX = desiredLeft + width - 6; // make sure we overlap
            if (desiredTop + arrowHeight < PopupPreview.mouseY) {
                arrowY = PopupPreview.mouseY - arrowHeight;
                arrowUrl = "popup_preview_rightbottom.png";
            }
            else {
                arrowY = desiredTop;
                arrowUrl = "popup_preview_righttop.png";
            }
        }
        else if (desiredLeft > PopupPreview.mouseX) {
            // 34x64
            arrowWidth = 34;
            arrowHeight = 64;
            arrowX = desiredLeft - arrowWidth + 4; // make sure we overlap
            if (desiredTop + arrowHeight < PopupPreview.mouseY) {
                arrowY = PopupPreview.mouseY - arrowHeight;
                arrowUrl = "popup_preview_leftbottom.png";
            }
            else {
                arrowY = desiredTop;
                arrowUrl = "popup_preview_lefttop.png";
            }
        }
        var arrow = q$('popupPreviewArrow');
        arrow.setStyle('left', arrowX + 'px');
        arrow.setStyle('top', arrowY + 'px');
        arrow.setStyle('width', arrowWidth + 'px');
        arrow.setStyle('height', arrowHeight + 'px');
        arrow.setStyle('background-image', 'url(../images/frames/' + arrowUrl + ')');
        Common.cshow(arrow);
        PopupPreview._previewOuter.setStyle('left', desiredLeft + 'px');
        PopupPreview._previewOuter.setStyle('top', desiredTop + 'px');
    };
    PopupPreview.Leave = function () {
        var popup = q$('popupPreviewDataform');
        if (!popup)
            return;
        clearTimeout(PopupPreview.timerControl);
        PopupPreview.hoverId = null;
        PopupPreview.element = null;
        Common.chide(popup);
        Common.chide('popupPreviewArrow');
    };
    PopupPreview.REQUEST_DELAY = 500;
    PopupPreview.DATAFORM = 1;
    PopupPreview.PROFILE = 2;
    PopupPreview.CONFERENCE = 3;
    PopupPreview.REP = 4;
    PopupPreview.mouseX = 0;
    PopupPreview.mouseY = 0;
    PopupPreview.timerControl = null;
    return PopupPreview;
}());
doOnPageReady(PopupPreview.initOnPageReady);

//include "MemoryManagement.js"
//include "Viewport.js"



// ButtonFixer.js

//xnclude "MemoryManagement.js"
/// <reference path="mootools.d.ts" />
/// <reference path="AfterStartupEvents.ts" />
var ButtonFixer = (function () {
    function ButtonFixer() {
    }
    // ButtonFixer only needed for IE
    ButtonFixer.checkBrowser = function () {
        return navigator.userAgent.toLowerCase().indexOf("msie") > -1;
    };
    ButtonFixer.Update = function (e) {
        if (!ButtonFixer.checkBrowser())
            return false;
        if (e === undefined) {
            e = document.body;
        }
        var buttons = q$(e).getElements('.smallRoundButton');
        for (var i = 0; i < buttons.length; i++) {
            ButtonFixer.FixButton(buttons[i], "smallRoundButton", "qSmallRoundButton");
        }
        return true;
    };
    ButtonFixer.FixButton = function (e, classToRemove, baseClassName) {
        var floatRight = false;
        var buttonText = q$(e).get('html');
        if (buttonText === null)
            buttonText = e.textContent;
        e = q$(e);
        e.set('html', '');
        if (e.getStyle('float') === 'right')
            floatRight = true;
        e.removeClass(classToRemove);
        e.addClass(baseClassName + "Left");
        if (floatRight)
            e.setStyle('float', 'right');
        var rightBorder = q$(document.createElement('span'));
        rightBorder.addClass(baseClassName + "Right");
        e.appendChild(rightBorder);
        var leftBorder = q$(document.createElement('span'));
        leftBorder.addClass(baseClassName);
        rightBorder.appendChild(leftBorder);
        q$(leftBorder).set('html', buttonText);
    };
    ButtonFixer.InvertButton = function (element, baseClassToRemove, baseClassToAdd) {
        if (!ButtonFixer.checkBrowser())
            return;
        if (element.hasClass(baseClassToRemove + "Left")) {
            element.removeClass(baseClassToRemove + "Left");
            element.addClass(baseClassToAdd + "Left");
            var spans = element.getElements('span');
            spans[0].removeClass(baseClassToRemove + "Right");
            spans[0].addClass(baseClassToAdd + "Right");
            spans[1].removeClass(baseClassToRemove);
            spans[1].addClass(baseClassToAdd);
        }
        var done = $$(".done");
        done.each(function (item) {
            item.removeClass("done");
        });
    };
    return ButtonFixer;
}());
doOnPageReady(ButtonFixer.Update);

//include "MemoryManagement.js"



// ActivityMonitor.js

/// <reference path="XML.ts"/>
/// <reference path="DateUtils.ts"/>
var ActivityMonitor = (function () {
    function ActivityMonitor() {
    }
    ActivityMonitor.init = function () {
        var lastActivityLeaseTime = ActivityMonitor.getTimeOfLastActivityLease();
        // when we load a page, remember the state of
        // last activity as of the previous page
        // (stored at unload time)
        if (lastActivityLeaseTime > 0) {
            // on load, set last local activity to last known act time from previous
            // window
            ActivityMonitor.lastLocalActivity = lastActivityLeaseTime;
        }
        // check for inactivity a little bit in advance of the server
        securityInactivityTimeout -= 10000;
        // and start event tracking
        ActivityMonitor.enableEventTracking();
        ActivityMonitor.startTimer();
        return true;
    };
    ActivityMonitor.getActiveTimeRemaining = function () {
        var msNow = DateUtils.msNow();
        var lastActivityLeaseTime = ActivityMonitor.getTimeOfLastActivityLease();
        var expirationTime = lastActivityLeaseTime + securityInactivityTimeout;
        // client expiry is a bit before server expiry
        return expirationTime - msNow; // how long till expiration?
        // if elapses in the future, set timer to check
    };
    ActivityMonitor.startTimer = function () {
        var millisTillExpiry = ActivityMonitor.getActiveTimeRemaining();
        // if elapses in the future, set timer to check
        if (millisTillExpiry > 0) {
            ActivityMonitor.timer = setTimeout(ActivityMonitor.checkAndUpdateActivityState, millisTillExpiry);
        }
        else {
            // already too old, don't bother checking whether to refresh or not
            ActivityMonitor.invalidateLastActivity();
        }
    };
    // Timer calls this just before expiration...
    ActivityMonitor.checkAndUpdateActivityState = function () {
        var msNow = DateUtils.msNow();
        // recent enough activity?
        if (msNow - ActivityMonitor.lastLocalActivity < securityInactivityTimeout) {
            ActivityMonitor.revalidateLastActivity();
        }
        else {
            ActivityMonitor.invalidateLastActivity();
        }
    };
    // we have been active: get new lease from the server
    ActivityMonitor.revalidateLastActivity = function () {
        // if we're on a "must refresh" page and we have been active,
        // then refresh or create a new lease even if the current lease
        // has been deleted (i.e. from some other tab)
        if (ActivityMonitor.refreshIfInactive()) {
            ActivityMonitor.requestActivityLease(function () {
                // success case
                ActivityMonitor.startTimer();
            }, function () {
                // failure case
                window.location.reload(true);
            });
            return;
        }
        // ok... here's we're on any other "don't care" page, but we still want
        // to track activity if we're within an activity lease
        //
        // if no cookie, we're already out of
        // our window of recent activity, just quit
        var expiry = readCookie('act');
        if (!expiry) {
            // if we're on a "don't care" page and we have no lease cookie,
            // just quit now... nothing to do
            return;
        }
        if (ActivityMonitor.currentPageIsSecure()) {
            ActivityMonitor.requestActivityLease(function (act) {
                // success case
                if (act) {
                    // reschedule activity check
                    ActivityMonitor.startTimer();
                }
            }, function () {
                // it was too late... inactive on the server
            });
        }
        else {
            var i = new Image(1, 1);
            i.src = "https://" + QSettings._secureDomain + "/refreshLastActivity?cb=" + DateUtils.msNow();
            // and record the browser's time
            gQCredentials.createLastActivityCookies(null);
            // reschedule activity check
            ActivityMonitor.startTimer();
        }
    };
    ActivityMonitor.invalidateLastActivity = function () {
        // Stop tracking events on this page as we're
        // going to be invalid anyway
        ActivityMonitor.disableEventTracking();
        // if we are on a "must refresh" page, explicitly invalidate
        // the activity cookie, then refresh to force us to go to
        // the password prompt
        if (ActivityMonitor.refreshIfInactive()) {
            var xmlAuth = XML.CreateDocument("<invalidateLastActivity></invalidateLastActivity>");
            Ajax.postAsXml(QSettings.postUrl(), xmlAuth, function () {
                // server has invalidated our activity key
                // force a refresh now
                ActivityMonitor.refreshPage();
            }, function (errorMessage) {
            });
        }
        // else
        // if we are on a "don't care" page, just let the activity key
        // time out on the server... no other action needed
    };
    ActivityMonitor.cancelTimerOnly = function () {
        ActivityMonitor.ignoreStopTimer = true;
    };
    ActivityMonitor.stopTimer = function () {
        if (ActivityMonitor.timer) {
            clearTimeout(ActivityMonitor.timer);
            ActivityMonitor.timer = null;
        }
    };
    ActivityMonitor.recordActivity = function () {
        ActivityMonitor.lastLocalActivity = DateUtils.msNow();
    };
    ActivityMonitor.refreshIfInactive = function () {
        return Pageparams.enforceInactivityCallback;
    };
    ActivityMonitor.setForceRefreshIfInactive = function (flag) {
        Pageparams.enforceInactivityCallback = flag;
    };
    ActivityMonitor.refreshPage = function () {
        var loc = window.location.href;
        if (loc.indexOf("reenter") === -1) {
            loc += Common.nextArgSep(loc) + "reenter=1";
        }
        window.location.href = loc;
    };
    ActivityMonitor.enableEventTracking = function () {
        if (!ActivityMonitor.trackEvents) {
            return;
        }
        var outer = q$('pageContainer');
        if (!outer) {
            return;
        }
        outer.addEvent('mousemove', function () {
            ActivityMonitor.recordActivity();
        });
        outer.addEvent('keyup', function () {
            ActivityMonitor.recordActivity();
        });
        window.addEvent('scroll', function () {
            ActivityMonitor.recordActivity();
        });
    };
    ActivityMonitor.disableEventTracking = function () {
        ActivityMonitor.trackEvents = false;
    };
    ActivityMonitor.getTimeOfLastActivityLease = function () {
        var cookieValue = readCookie('act');
        if (cookieValue === null)
            return 0;
        return Number(cookieValue);
    };
    ActivityMonitor.requestActivityLease = function (success, failure) {
        var xmlRefresh = XML.CreateDocument("<refreshLastActivity></refreshLastActivity>");
        Ajax.postAsXml(QSettings.postUrl(), xmlRefresh, function (resp) {
            var respDoc = XML.CreateDocument(resp);
            var act = respDoc.documentElement.getAttribute("act");
            gQCredentials.createLastActivityCookies(act);
            success(act);
        }, function () {
            failure();
        });
    };
    ActivityMonitor.currentPageIsSecure = function () {
        return (window.location.protocol.toLowerCase().indexOf('https') > -1);
    };
    ActivityMonitor.timer = null;
    ActivityMonitor.lastLocalActivity = 0;
    ActivityMonitor.enforceInactivityCallback = false;
    ActivityMonitor.trackEvents = true;
    ActivityMonitor.ignoreStopTimer = false;
    return ActivityMonitor;
}());
var securityInactivityTimeout = 0;
doOnPageReady(ActivityMonitor.init);
window.addEvent('beforeunload', ActivityMonitor.stopTimer);




// QModalDialog.js

/* Based on
 * http://www.logiclabz.com/javascript/create-a-modal-window-div-element-with-javascript-on-html.aspx
 */
var QModalDialog = (function () {
    function QModalDialog(dialogDiv, titlep, hideClose) {
        this.confirmScreen = false;
        this.height = '455px'; //css style height value
        this.visibleTitle = true;
        this.title = (titlep) ? titlep : dialogDiv.title;
        if (!this.title)
            this.title = '';
        this.dialogDiv = dialogDiv;
        this.pageContentIFrame = null;
        this.onhide = null;
        this.TITLEBARHEIGHT = 35;
        if (hideClose) {
            this.hideClose = hideClose;
        }
    }
    QModalDialog.prototype.setTitle = function (title) {
        this.title = title;
    };
    QModalDialog.prototype.getTitle = function () {
        return this.title;
    };
    /**
     * Show/ hide the title
     * By default the title is shown
     * @param {boolean} show
     */
    QModalDialog.prototype.showTitle = function (show) {
        this.visibleTitle = show;
    };
    /**
     * Set the height css style  for the main container of the dialog
     * This method doesn't update the height directly. For new value to be visible, it should be followed either by show() or  update()
     * @param {string} height
     */
    QModalDialog.prototype.setHeight = function (height) {
        this.height = height;
    };
    QModalDialog.prototype.modifyTitlebarText = function (newTitle) {
        q$('xdivtitletext' + this.depth).set('html', newTitle);
        //this.titletext
    };
    /**
     * Sets the iframe and loads the given source url in it
     * If the source url is null or empty, then it just creates the iframe
     * @param {string} sourceUrl
     */
    QModalDialog.prototype.setContent = function (sourceUrl) {
        var needsInsertion = false;
        var childElems = this.dialogDiv.getElementsByTagName('iframe');
        if (childElems && childElems.length > 0) {
            this.pageContentIFrame = childElems[0];
        }
        else {
            // must have a random ID each time, to fix webkit bug... see bugzilla 7411
            var uniqueID = "i" + DateUtils.msNow();
            this.pageContentIFrame = q$(document.createElement('iframe'));
            this.pageContentIFrame.setAttribute('id', uniqueID);
            this.pageContentIFrame.setAttribute('frameBorder', '0');
            this.pageContentIFrame.setAttribute('scrolling', 'no');
            this.pageContentIFrame.setStyle('width', '100%');
            this.pageContentIFrame.setStyle('height', '100%');
            this.pageContentIFrame.setStyle('border', 'none');
            this.pageContentIFrame.setStyle('overflow', 'hidden');
            needsInsertion = true;
        }
        if (sourceUrl) {
            this.pageContentIFrame.setAttribute('src', sourceUrl);
        }
        if (needsInsertion)
            this.dialogDiv.appendChild(this.pageContentIFrame);
    };
    QModalDialog.prototype.updateHideClose = function (hideclose) {
        this.hideClose = hideclose;
        if (hideclose == true && this.titlebar) {
            if (this.titleclose)
                this.titlebar.removeChild(this.titleclose);
        }
        else {
            if (!this.titleclose && this.titlebar) {
                this.createCloseButton();
            }
        }
    };
    QModalDialog.prototype.createCloseButton = function () {
        this.titleclose = q$(document.createElement('div'));
        this.titleclose.addClass('modalDialogClose');
        this.titleclose.setAttribute('id', 'xdivtitleclose' + this.depth);
        this.titleclose.addEvent('click', function (event) {
            var id = event.target.id;
            var depth = id.substring(14);
            var target = QModalDialog.qModalDialogStack[depth - 1];
            target.titleclose.removeClass('hover');
            if ((window.location.href.indexOf("inbox") > -1) && this.confirmScreen)
                setTimeout(function () {
                    window.location.href = '/home/inbox';
                }, 100);
            target.hide();
        });
        this.titleclose.addEvent('mouseover', function (event) {
            var id = event.target.id;
            var depth = id.substring(14);
            var target = QModalDialog.qModalDialogStack[depth - 1];
            target.titleclose.addClass('hover');
        });
        this.titleclose.addEvent('mouseout', function (event) {
            var id = event.target.id;
            var depth = id.substring(14);
            var target = QModalDialog.qModalDialogStack[depth - 1];
            if (target != null) {
                target.titleclose.removeClass('hover');
            }
        });
        this.titleclosetext = q$(document.createElement('span'));
        this.titleclosetext.addClass('close');
        this.titleclosetext.setAttribute('id', 'xdivtitleclosetext' + this.depth);
        this.titleclosetext.addEvent('click', function (event) {
            var id = event.target.id;
            var depth = id.substring(18);
            var target = QModalDialog.qModalDialogStack[depth - 1];
            target.titleclose.removeClass('hover');
            if ((window.location.href.indexOf("inbox") > -1) && this.confirmScreen)
                setTimeout(function () {
                    window.location.href = '/home/inbox';
                }, 100);
            target.hide();
            if (event && event.stopPropagation) {
                event.stopPropagation();
            }
            else {
                event = window.event;
                event.cancelBubble = true;
            }
        });
        this.titleclosetext.addEvent('mouseover', function (event) {
            var id = event.target.id;
            var depth = id.substring(18);
            var target = QModalDialog.qModalDialogStack[depth - 1];
            target.titleclose.addClass('hover');
            if (event && event.stopPropagation) {
                event.stopPropagation();
            }
            else {
                event = window.event;
                event.cancelBubble = true;
            }
        });
        this.titleclosetext.addEvent('mouseout', function (event) {
            var id = event.target.id;
            var depth = id.substring(18);
            var target = QModalDialog.qModalDialogStack[depth - 1];
            if (target) {
                target.titleclose.removeClass('hover');
            }
            if (event && event.stopPropagation) {
                event.stopPropagation();
            }
            else {
                event = window.event;
                event.cancelBubble = true;
            }
        });
        this.titleclose.appendChild(this.titleclosetext);
        this.titlebar.appendChild(this.titleclose);
        this.titleclosetext.set('html', QSTR.close);
    };
    QModalDialog.prototype.buildDlg = function () {
        this.createDropShadow(this.depth);
        this.graylayer = Common.newEltOfClass('div', null, 'xdivgraylayer' + this.depth);
        this.graylayer.setStyle('position', 'absolute');
        this.graylayer.setStyle('top', '0px');
        this.graylayer.setStyle('left', '0px');
        this.graylayer.setStyle('zIndex', this.getZIndex() - 2);
        this.graylayer.setStyle('backgroundColor', '#2b4755');
        this.graylayer.set('opacity', .8);
        document.body.appendChild(this.graylayer);
        this.waitifrm = Common.newEltOfClass('iframe', null, 'xmaskframe' + this.depth);
        this.waitifrm.setStyle('position', 'absolute');
        this.waitifrm.setStyle('top', '0px');
        this.waitifrm.setStyle('left', '0px');
        this.waitifrm.setStyle('zIndex', 98 * this.depth);
        this.waitifrm.setStyle('backgroundColor', '#000000');
        this.waitifrm.set('opacity', 0);
        document.body.appendChild(this.waitifrm);
        this.titlebar = Common.newEltOfClass('div', null, 'xdivtitlebar' + this.depth);
        Common.chide(this.titlebar);
        if (this.dialogDiv.childNodes.length > 0) {
            this.dialogDiv.insertBefore(this.titlebar, this.dialogDiv.childNodes[0]);
        }
        else {
            this.dialogDiv.appendChild(this.titlebar);
        }
        if (!this.hideClose) {
            this.createCloseButton();
        }
        //adding left icon to titlebar
        this.titleContainer = Common.newEltOfClass('div', 'modalDialogTitleContainer', 'xdivtitleContainer' + this.depth);
        this.titlebar.appendChild(this.titleContainer);
        this.titletexticon = Common.newEltOfClass('div', 'modalDialogTitleIcon t', 'xdivtitletexticon' + this.depth);
        this.titleContainer.appendChild(this.titletexticon);
        this.titletext = Common.newEltOfClass('div', 'modalDialogTitle', 'xdivtitletext' + this.depth);
        this.titleContainer.appendChild(this.titletext);
        this.titleContainer.appendChild(Common.newEltOfClass('hr', 'top-referral-hr', 'xdivtitleSep' + this.depth));
    };
    QModalDialog.prototype.xxxDlg = function () {
        this.waitifrm = document.getElementById('xmaskframe' + this.depth);
        for (var i = 0; i < QModalDialog.divs.length; ++i) {
            var divname = QModalDialog.divs[i];
            this[divname] = document.getElementById('xdiv' + divname + this.depth);
        }
        if (this.hideClose) {
            if (this.titleclose)
                this.titlebar.removeChild(this.titleclose);
        }
        else {
            if (!this.titleclose)
                this.createCloseButton();
        }
    };
    QModalDialog.prototype.show = function (onhide) {
        this.onhide = onhide;
        QModalDialog.qModalDialogStack.push(this);
        this.depth = QModalDialog.qModalDialogStack.length;
        var dlgRootEltID = 'xdivgraylayer' + this.depth;
        var dlgRootElt = document.getElementById(dlgRootEltID);
        if (!dlgRootElt)
            this.buildDlg();
        else
            this.xxxDlg();
        this.resize();
        this.setDivDisplay('block');
        this.dialogDiv.addClass('modalDialog');
        this.dialogDiv.setStyle('zIndex', this.getZIndex());
        this.dialogDiv = q$(this.dialogDiv);
        this.titletext.set('html', this.title);
        this.titlebar.addClass('modalDialogTop');
        Common.cshow(this.dialogDiv);
        Common.cshow(this.titlebar);
        this.update(); // should be called before any other adjustments
        QModalDialog.clearCloseDlgFlag();
        QModalDialog.clearNewTitleFlag();
        QModalDialog.clearGotolocation();
        if (QModalDialog.qModalDialogStack.length == 1) {
            setTimeout(QModalDialog.checkDialogCloseCookie, 200);
            setTimeout(QModalDialog.checkChangeTitleCookie, 200);
        }
        this.setActionListAutoPlay(false);
        if (window['hasQModalResize'] != true) {
            window.hasQModalResize = true;
            if (window.addEventListener) {
                window.addEventListener('resize', this.resize, false);
            }
            else if (window.attachEvent) {
                window.attachEvent('onresize', this.resize);
            }
        }
    };
    /**
     * Update the UI elements according to the new set values
     * This method should only be called once the dialog is initialized ans built
     */
    QModalDialog.prototype.update = function () {
        // update the visibility of the title
        Common.cShowOrHide(this.titleContainer, this.visibleTitle);
        //update the dialog height
        this.dialogDiv.setStyle('height', this.height);
        if (this.pageContentIFrame) {
            this.pageContentIFrame.setStyle('height', (this.dialogDiv.offsetHeight - this.titlebar.offsetHeight - 5) + 'px');
        }
        // udpate the dialog position
        var myWidth = this.dialogDiv.offsetWidth;
        var myHeight = this.dialogDiv.offsetHeight;
        var myTop = (((Viewport.windowHeight() / 2) + Viewport.scrollY()) + this.TITLEBARHEIGHT - (myHeight / 2));
        if (myTop < 50) {
            myTop = 50;
        }
        var myLeft = (((Viewport.windowWidth() / 2) + Viewport.scrollX()) - (myWidth / 2));
        this.dialogDiv.style.top = myTop + 'px';
        this.dialogDiv.style.left = myLeft + 'px';
        this.positionDropShadow(myTop - 34, myLeft, myWidth, myHeight + 34);
    };
    QModalDialog.prototype.setActionListAutoPlay = function (boolean) {
        Common.setAutoPlayAllowed("modal", boolean);
    };
    QModalDialog.prototype.setDivDisplay = function (noneOrBlock) {
        this.waitifrm.style.display = noneOrBlock;
        for (var i = 0; i < QModalDialog.divs.length; ++i) {
            var divname = QModalDialog.divs[i];
            var div = this[divname];
            if (div) {
                div.style.display = noneOrBlock;
            }
        }
    };
    QModalDialog.prototype.getZIndex = function () {
        return 1400 + 101 * this.depth;
    };
    QModalDialog.prototype.createDropShadow = function (depth) {
        this.shadowTopLeft = Common.newEltOfClass('div', 'dialogShadowTopLeft dialogShadow', 'xdivshadowTopLeft' + depth);
        this.shadowTopLeft.setStyle('zIndex', this.getZIndex());
        document.body.appendChild(this.shadowTopLeft);
        this.shadowTopMiddle = Common.newEltOfClass('div', 'dialogShadowTopMiddle dialogShadow', 'xdivshadowTopMiddle' + depth);
        this.shadowTopMiddle.setStyle('zIndex', this.getZIndex());
        document.body.appendChild(this.shadowTopMiddle);
        this.shadowTopRight = Common.newEltOfClass('div', 'dialogShadowTopRight dialogShadow', 'xdivshadowTopRight' + depth);
        this.shadowTopRight.setStyle('zIndex', this.getZIndex());
        document.body.appendChild(this.shadowTopRight);
        this.shadowMiddleLeft = Common.newEltOfClass('div', 'dialogShadowMiddleLeft dialogShadow', 'xdivshadowMiddleLeft' + depth);
        this.shadowMiddleLeft.setStyle('zIndex', this.getZIndex());
        document.body.appendChild(this.shadowMiddleLeft);
        this.shadowMiddleRight = Common.newEltOfClass('div', 'dialogShadowMiddleRight dialogShadow', 'xdivshadowMiddleRight' + depth);
        this.shadowMiddleRight.setStyle('zIndex', this.getZIndex());
        document.body.appendChild(this.shadowMiddleRight);
        this.shadowBottomLeft = Common.newEltOfClass('div', 'dialogShadowBottomLeft dialogShadow', 'xdivshadowBottomLeft' + depth);
        this.shadowBottomLeft.setStyle('zIndex', this.getZIndex());
        document.body.appendChild(this.shadowBottomLeft);
        this.shadowBottomMiddle = Common.newEltOfClass('div', 'dialogShadowBottomMiddle dialogShadow', 'xdivshadowBottomMiddle' + depth);
        this.shadowBottomMiddle.setStyle('zIndex', this.getZIndex());
        document.body.appendChild(this.shadowBottomMiddle);
        this.shadowBottomRight = Common.newEltOfClass('div', 'dialogShadowBottomRight dialogShadow', 'xdivshadowBottomRight' + depth);
        this.shadowBottomRight.setStyle('zIndex', this.getZIndex());
        document.body.appendChild(this.shadowBottomRight);
    };
    QModalDialog.prototype.positionDropShadow = function (top, left, width, height) {
        this.shadowTopLeft.style.left = (left - 15) + 'px';
        this.shadowTopLeft.style.top = (top - 15) + 'px';
        this.shadowTopMiddle.style.left = (left) + 'px';
        this.shadowTopMiddle.style.top = (top - 15) + 'px';
        this.shadowTopMiddle.style.width = (width) + 'px';
        this.shadowTopRight.style.left = (left + width) + 'px';
        this.shadowTopRight.style.top = (top - 15) + 'px';
        this.shadowMiddleLeft.style.left = (left - 15) + 'px';
        this.shadowMiddleLeft.style.top = (top) + 'px';
        this.shadowMiddleLeft.style.height = (height) + 'px';
        this.shadowMiddleRight.style.left = (left + width) + 'px';
        this.shadowMiddleRight.style.top = (top) + 'px';
        this.shadowMiddleRight.style.height = (height) + 'px';
        this.shadowBottomLeft.style.left = (left - 15) + 'px';
        this.shadowBottomLeft.style.top = (top + height) + 'px';
        this.shadowBottomMiddle.style.left = (left) + 'px';
        this.shadowBottomMiddle.style.top = (top + height) + 'px';
        this.shadowBottomMiddle.style.width = (width) + 'px';
        this.shadowBottomRight.style.left = (left + width) + 'px';
        this.shadowBottomRight.style.top = (top + height) + 'px';
    };
    QModalDialog.prototype.resize = function () {
        var dsh = document.documentElement.scrollHeight;
        var dch = document.documentElement.clientHeight;
        var dsw = document.documentElement.scrollWidth;
        var dcw = document.documentElement.clientWidth;
        var bdh = (dsh > dch) ? dsh : dch;
        var bdw = (dsw > dcw) ? dsw : dcw;
        for (var i = 0; i < QModalDialog.qModalDialogStack.length; ++i) {
            var qmd = QModalDialog.qModalDialogStack[i];
            qmd.waitifrm.style.height = qmd.graylayer.style.height = bdh + 'px';
            qmd.waitifrm.style.width = qmd.graylayer.style.width = bdw + 'px';
        }
    };
    QModalDialog.prototype.hide = function () {
        if (QModalDialog.qModalDialogStack.length == 0)
            return;
        if (this.onhide) {
            if (!this.onhide())
                return false;
        }
        this.setActionListAutoPlay(true);
        QModalDialog.qModalDialogStack.pop();
        Common.chide(this.dialogDiv);
        this.dialogDiv.removeClass('modalDialog');
        Common.chide(this.titlebar);
        this.titlebar.removeClass('modalDialog');
        this.setDivDisplay('none');
        return true;
    };
    QModalDialog.prototype.changeTitle = function () {
        if (QModalDialog.qModalDialogStack.length == 0)
            return false;
        this.setActionListAutoPlay(true);
        var newtitle = decodeURIComponent(readCookie('title'));
        if (newtitle != null && newtitle != '') {
            this.modifyTitlebarText(newtitle);
            if (newtitle == QSTR.messageConfirmation)
                this.confirmScreen = true;
        }
        return true;
    };
    QModalDialog.clearCloseDlgFlag = function () {
        createCookie('closeDialog', '');
    };
    QModalDialog.clearNewTitleFlag = function () {
        createCookie('changeTitle', '');
    };
    QModalDialog.clearGotolocation = function () {
        createCookie('gotolocation', '');
    };
    QModalDialog.requestNewTitle = function (newTitle) {
        createCookie('title', newTitle);
        createCookie('changeTitle', 'true');
    };
    QModalDialog.requestDlgClose = function (destUrl) {
        createCookie('gotolocation', destUrl || "");
        createCookie('closeDialog', 'true');
    };
    QModalDialog.checkDialogCloseCookie = function () {
        if (QModalDialog.qModalDialogStack.length == 0)
            return;
        var cookie = readCookie('closeDialog');
        var okToClose = false;
        if (cookie) {
            QModalDialog.clearCloseDlgFlag();
            var dlg = QModalDialog.qModalDialogStack[0];
            okToClose = dlg.hide();
            var gotolocation = readCookie('gotolocation');
            if (gotolocation)
                window.parent.location.href = gotolocation;
        }
        if (!okToClose) {
            setTimeout(QModalDialog.checkDialogCloseCookie, 300);
        }
    };
    QModalDialog.checkChangeTitleCookie = function () {
        if (QModalDialog.qModalDialogStack.length == 0)
            return;
        var cookieVal = readCookie('changeTitle');
        var okToChange = false;
        if (cookieVal) {
            QModalDialog.clearNewTitleFlag();
            var dlg = QModalDialog.qModalDialogStack[0];
            okToChange = dlg.changeTitle();
        }
        if (!okToChange) {
            setTimeout(QModalDialog.checkChangeTitleCookie, 300);
        }
    };
    QModalDialog.qModalDialogStack = [];
    QModalDialog.divs = [
        'graylayer', 'titlebar', 'titleContainer', 'titletexticon', 'titletext', 'titleclose',
        'shadowTopLeft', 'shadowTopMiddle', 'shadowTopRight',
        'shadowMiddleLeft', 'shadowMiddleRight',
        'shadowBottomLeft', 'shadowBottomMiddle', 'shadowBottomRight'
    ];
    return QModalDialog;
}());




// DialogUtils.js

/// <reference path="Window.d.ts"/>
/// <reference path="mootools.d.ts" />
/// <reference path="CommonWeb.ts" />
var DialogElements = (function () {
    function DialogElements(outer, inner, bg) {
        this.outerEltName = outer;
        this.innerEltName = inner;
        this.bgEltName = bg;
    }
    return DialogElements;
}());
var DialogUtilsClass = (function () {
    function DialogUtilsClass() {
    }
    DialogUtilsClass.prototype.initDlg = function (dlgElts, containerElt, callback) {
        this.removeBodyScrollBars(callback);
        Common.cshow(dlgElts.outerEltName);
        this.handleDialogResize(dlgElts.innerEltName, dlgElts.bgEltName, containerElt);
    };
    DialogUtilsClass.prototype.closeDlg = function (dlgElts) {
        this.restoreBodyScrollBars();
        Common.chide(dlgElts.outerEltName);
    };
    DialogUtilsClass.prototype.removeBodyScrollBars = function (callback) {
        var b = document.body;
        b.addClass(DialogUtilsClass.strScrollBarHidden);
        var innerBody = q$(DialogUtilsClass.strInnerBody);
        var viewportHeight = window.getSize().y;
        var viewportWidth = window.getSize().x;
        innerBody.setStyle('height', (viewportHeight - 50) + 'px');
        innerBody.setStyle('width', (viewportWidth - 50) + 'px');
        setTimeout(function () {
            if (Browser.name != 'ie' || Browser.version != 7) {
                var viewportHeight_1 = window.getSize().y;
                b.setStyle('height', viewportHeight_1 + 'px');
            }
            b.scroll = "no"; //ie7
            if (callback) {
                callback();
            }
        }, 10);
    };
    DialogUtilsClass.prototype.restoreBodyScrollBars = function () {
        var b = document.body;
        b.removeClass(DialogUtilsClass.strScrollBarHidden);
        b.scroll = ""; //ie7
        b.setStyle('width', 'auto');
        b.setStyle('height', 'auto');
        var innerBodyElt = q$(DialogUtilsClass.strInnerBody);
        if (innerBodyElt) {
            innerBodyElt.setStyle('width', 'auto');
            innerBodyElt.setStyle('height', 'auto');
        }
    };
    DialogUtilsClass.prototype.resizeOpaqueBackground = function (bgElement, elem) {
        var bodySize;
        var scrollY, scrollX;
        var b;
        if (typeof elem == 'undefined' || elem == null) {
            b = q$(document.body);
            bodySize = DialogUtilsClass.getPageRealSize(); //bodySize = b.getSize();
            scrollY = 0; // window.getScroll().y;
        }
        else {
            bodySize = elem.getSize();
            if (elem.id == DialogUtilsClass.strRightPanel) {
                bodySize.y = 640;
            }
            scrollY = elem.offsetTop;
            scrollX = elem.offsetLeft;
        }
        bgElement = q$(bgElement);
        bgElement.setStyle('top', scrollY + 'px');
        var leftStyle = (elem == null) ? '0' : scrollX + 'px';
        bgElement.setStyle('left', leftStyle);
        bgElement.setStyle('width', bodySize.x + 'px');
        bgElement.setStyle('height', bodySize.y + 'px');
    };
    DialogUtilsClass.prototype.handleDialogResize = function (strInnerDialog, backgroundElement, containerElt) {
        var bodySize, scrollX;
        var scrollY = window.getScroll().y;
        var viewportHeight = window.getSize().y;
        if (!containerElt) {
            var b = q$(document.body);
            bodySize = b.getSize();
            var innerBody = q$(DialogUtilsClass.strInnerBody);
            if (innerBody) {
                innerBody.setStyle('width', bodySize.x + 'px');
                innerBody.setStyle('height', (viewportHeight + scrollY) + 'px');
            }
        }
        else {
            bodySize = containerElt.getSize();
            bodySize.y = 640;
            scrollY = (scrollY < 50) ? scrollY + 100 : scrollY;
            scrollX = containerElt.offsetLeft;
        }
        var innerDlgElt = q$(strInnerDialog);
        var innerDialogSize = innerDlgElt.getSize();
        var desiredWidth = innerDialogSize.x;
        var desiredHeight = innerDialogSize.y;
        var desiredTop = scrollY + (bodySize.y - desiredHeight) / 2;
        desiredTop = Math.max(desiredTop, 30);
        var desiredLeft = (!containerElt) ?
            (bodySize.x - desiredWidth) / 2 :
            scrollX + (bodySize.x - desiredWidth) / 2;
        desiredLeft = Math.max(desiredLeft, 20);
        innerDlgElt.setStyle('left', desiredLeft + 'px');
        innerDlgElt.setStyle('top', desiredTop + 'px');
        if (!Common.isAndroid() && !Common.isIOS() && (desiredHeight > bodySize.y)) {
            innerDlgElt.setStyle('height', (desiredHeight * 0.85) + 'px');
        }
        else {
            innerDlgElt.setStyle('height', '');
        }
        //innerDlgElt.setStyle('overflow-y', 'auto');
        // resize background to stick to the sides
        if (backgroundElement) {
            DialogUtils.resizeOpaqueBackground(backgroundElement, containerElt);
        }
    };
    // names of elements on page referenced when no containing element specified
    DialogUtilsClass.strScrollBarHidden = 'scrollBarHidden';
    DialogUtilsClass.strInnerBody = 'innerBody';
    DialogUtilsClass.strRightPanel = 'rightPanel';
    /**
     * get the shown page real size
     * @returns {{x: number; y: number}}
     */
    DialogUtilsClass.getPageRealSize = function () {
        var body = document.body, html = document.documentElement;
        var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
        var width = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth);
        return { x: width, y: height };
    };
    return DialogUtilsClass;
}());
var DialogUtils = new DialogUtilsClass();




// DelayedBackground.js

/// <reference path="../Window.d.ts" />
/// <reference path="../Common.d.ts" />
var DelayedBackgroundClass = (function () {
    function DelayedBackgroundClass() {
    }
    DelayedBackgroundClass.prototype.onStartup = function () {
        window.addEvent('scroll', DelayedBackground.loadImages.bind(DelayedBackground));
        window.addEvent('resize', DelayedBackground.loadImages.bind(DelayedBackground));
        this.loadImages();
        return false;
    };
    DelayedBackgroundClass.prototype.loadImages = function (objContainer) {
        var elementsToConsider;
        var hideIfAbove;
        var hideIfBelow;
        if (!objContainer) {
            var viewPortScroll = window.getScroll().y;
            var windowHeight = window.getSize().y;
            var viewPortBottom = windowHeight + viewPortScroll;
            hideIfAbove = viewPortScroll - (windowHeight * 2);
            hideIfBelow = viewPortBottom + (windowHeight * 2);
            elementsToConsider = $$(".delayedBackgroundStyle");
        }
        else {
            hideIfAbove = objContainer.getCoordinates().top;
            hideIfBelow = hideIfAbove + objContainer.offsetHeight;
            elementsToConsider = objContainer.getElements(".delayedBackgroundStyle");
        }
        this.processImages(elementsToConsider, hideIfAbove, hideIfBelow);
    };
    DelayedBackgroundClass.prototype.loadAllImages = function (objContainer) {
        var hideIfAbove = -1;
        var hideIfBelow = 100000;
        var elementsToConsider;
        if (!objContainer) {
            elementsToConsider = $$(".delayedBackgroundStyle");
        }
        else {
            elementsToConsider = objContainer.getElements(".delayedBackgroundStyle");
        }
        this.processImages(elementsToConsider, hideIfAbove, hideIfBelow);
    };
    DelayedBackgroundClass.prototype.processImages = function (elementsToConsider, hideIfAbove, hideIfBelow) {
        for (var i = 0; i < elementsToConsider.length; ++i) {
            var elem = elementsToConsider[i];
            var shouldShowBackground = false;
            var offset = elem.getCoordinates().top;
            if ((offset + elem.offsetHeight > hideIfAbove) && (offset < hideIfBelow)) {
                shouldShowBackground = true;
            }
            if (shouldShowBackground !== elem.shouldShowBackground) {
                elem.shouldShowBackground = shouldShowBackground;
                if (!shouldShowBackground) {
                    this.hideAnImage(elem);
                }
                else {
                    this.loadAnImage(elem);
                }
            }
        }
    };
    DelayedBackgroundClass.prototype.hideAnImage = function (elem) {
        if (elem.nodeName.toLowerCase() === 'img')
            elem.src = null;
        else
            elem.style.backgroundImage = "";
    };
    DelayedBackgroundClass.prototype.loadAnImage = function (elem) {
        var desired = elem.attributes.delayedBackgroundStyle.value;
        if (elem.nodeName.toLowerCase() === 'img')
            elem.src = desired;
        else
            elem.style.backgroundImage = "url(" + desired + ")";
        if (!desired) {
            // this is useful in th case of news channel renderers to shrink completely the image container
            elem.style.display = 'none';
        }
        else {
            elem.style.display = '';
        }
    };
    return DelayedBackgroundClass;
}());
var DelayedBackground = new DelayedBackgroundClass();
doOnPageReady(DelayedBackground.onStartup.bind(DelayedBackground));




// QScroller.js

/// <reference path="mootools.d.ts" />
/// <reference path="feature/DelayedBackground.ts" />
//xnclude "Viewport.js"
//xnclude "feature/DelayedBackground.js"
var IScrollBar = (function () {
    function IScrollBar() {
        this.WHEEL_SPEED = 40;
        // PAGE_PADDING:number = 15;
        this.HANDLE_HEIGHT = 40;
        this.UP_DOWN_ARROW_SIZE = 15;
        this.lastScrollTime = 0;
        this.scrollWrappers = [];
    }
    IScrollBar.prototype._doNothing = function (ev) {
        ev.preventDefault();
    };
    IScrollBar.prototype.EnsureBodyWheelEvent = function () {
        if (this.bodyWheelEvent)
            return;
        var tempThis = this;
        this.bodyWheelEvent = function (ev) {
            for (var i = 0; i < tempThis.scrollWrappers.length; i++) {
                var moredialog = q$('moreDialogContents');
                var scrwrap = tempThis.scrollWrappers[i];
                if (scrwrap.collides(ev.page.x, ev.page.y)) {
                    if (scrwrap.handleScroll(ev)) {
                        if (moredialog)
                            DelayedBackground.loadImages(scrwrap.scrollContents);
                        tempThis.lastScrollTime = new Date().getTime();
                        ev.preventDefault();
                    }
                    return;
                }
            }
            if (new Date().getTime() - this._lastScrollTime < 500) {
                ev.preventDefault();
            }
        };
        q$(window).addEvent('mousewheel', this.bodyWheelEvent);
        q$(document.body).addEvent('mousewheel', this.bodyWheelEvent);
    };
    IScrollBar.INST = new IScrollBar();
    return IScrollBar;
}());
var ScrollBarWrapper = (function () {
    function ScrollBarWrapper(e, desiredVerticalOffset) {
        IScrollBar.INST.EnsureBodyWheelEvent();
        this.timeOfLastRejectedWheel = 0;
        this.e = q$(e);
        this.autoAdjustWindow = false;
        this.allowWindowScroll = true;
        this.newTicks = {};
        this.desiredVerticalOffset = desiredVerticalOffset;
        if (this.desiredVerticalOffset == null)
            this.desiredVerticalOffset = 0;
        this.scrollContents = q$(e).getElement('.scrollContents');
        this.scrollOffset = this.scrollContents.getScroll().y;
        this.outerScrollBarHeight = q$(e).getSize().y;
        this.innerScrollBarHeight = Math.max(this.outerScrollBarHeight - 2 * IScrollBar.INST.UP_DOWN_ARROW_SIZE, 0);
        this.totalScrollableContentHeight = this.scrollContents.getScrollSize().y;
        // if no comments, just avoid division by zero
        if (this.totalScrollableContentHeight == 0)
            this.totalScrollableContentHeight = this.outerScrollBarHeight + 1;
        this.scrollContents.setStyle('height', this.outerScrollBarHeight);
        this.scrollBar = e.getElement('.scrollBar');
        this.scrollBarUpArrow = e.getElement('.scrollBarUpArrow');
        this.scrollBarDownArrow = e.getElement('.scrollBarDownArrow');
        this.scrollBarThumb = e.getElement('.scrollBarHandle');
        this.outerScrollBarTop = q$(this.scrollBar).getTop();
        this.innerScrollBarTop = this.outerScrollBarTop + IScrollBar.INST.UP_DOWN_ARROW_SIZE;
        var mm = Math.max((this.innerScrollBarHeight / this.totalScrollableContentHeight) * this.innerScrollBarHeight, IScrollBar.INST.HANDLE_HEIGHT);
        this.scrollBarThumbHeight = Math.min(mm, (this.innerScrollBarHeight / 2));
        this.scrollBarThumb.setStyle('height', this.scrollBarThumbHeight);
        this.scrollBar.setStyle('height', this.outerScrollBarHeight);
        this.scrollBarThumb.setStyle('top', IScrollBar.INST.UP_DOWN_ARROW_SIZE);
        this.findNewTicks();
        /**
         * Any mousedown or mousemove within the scrollbar area fires this
         */
        this.updateFromEvent = function (ev, timeout) {
            var mousePos = ev.page.y;
            var relativePos = mousePos - this.outerScrollBarTop;
            if (this.isUpArrowClick(relativePos)) {
                this.doUpArrowClick();
            }
            else if (this.isDownArrowClick(relativePos)) {
                this.doDownArrowClick();
            }
            else {
                this.lastMousePosSinceDragStart = mousePos;
                var scrollDirection = this.isEventAboveBelowOrOnThumb(mousePos);
                // A simple click (vs a drag) over the scrollBarThumb itself should do nothing
                if (scrollDirection == 0 && !this.isDragging(mousePos)) {
                    return;
                }
                var delta = scrollDirection * this.innerScrollBarHeight;
                var newScrollOffset = this.scrollOffset + delta;
                var maxScrollOffset = this.totalScrollableContentHeight - this.innerScrollBarHeight;
                if (newScrollOffset < 0)
                    newScrollOffset = 0;
                else if (newScrollOffset > maxScrollOffset)
                    newScrollOffset = maxScrollOffset;
                this.scrollOffset = newScrollOffset;
            }
            this.updateFromScrollOffset();
            timeout = (!timeout) ? 500 : 100;
            if (this._updateFromEventInterval != null) {
                clearTimeout(this._updateFromEventInterval);
                this._updateFromEventInterval = null;
            }
            var tempThis = this;
            this._updateFromEventInterval = setTimeout(function () {
                tempThis.updateFromEvent(ev, timeout);
            }, timeout);
        }.bind(this);
        this.endDrag = function () {
            clearTimeout(this._updateFromEventInterval);
            this._updateFromEventInterval = null;
            var doc = document;
            doc.removeEvent('mousemove', this.updateFromEvent);
            doc.removeEvent('mouseup', this.endDrag);
            doc.removeEvent('mouseleave', this.endDrag);
            doc.removeEvent('selectstart', IScrollBar.INST._doNothing);
            var moredialog = q$('moreDialogContents');
            if (moredialog)
                DelayedBackground.loadImages(this.scrollContents);
            if (this.autoAdjustWindow) {
                this.lockToTop();
            }
        }.bind(this);
        this.startDrag = function (ev) {
            this.lastMousePosSinceDragStart = ev.page.y;
            var doc = document;
            doc.addEvent('mousemove', this.updateFromEvent);
            doc.addEvent('mouseup', this.endDrag);
            doc.addEvent('mouseleave', this.endDrag);
            doc.addEvent('selectstart', IScrollBar.INST._doNothing);
            this.updateFromEvent(ev);
            ev.preventDefault();
        }.bind(this);
        this.scrollBar.addEvent('mousedown', function (ev) {
            this.startDrag(ev);
        }.bind(this));
        this.scrollBar.addEvent('mouseenter', function (ev) {
            this.scrollBar.addClass('hover');
        }.bind(this));
        this.scrollBar.addEvent('mouseleave', function (ev) {
            this.scrollBar.removeClass('hover');
        }.bind(this));
        this.updateFromScrollOffset();
        this.readjust();
        this.boundLockToTop = function () { this.lockToTop(); }.bind(this);
        IScrollBar.INST.scrollWrappers.push(this);
    }
    ScrollBarWrapper.prototype.isUpArrowClick = function (relativePos) {
        return (relativePos < IScrollBar.INST.UP_DOWN_ARROW_SIZE);
    };
    ScrollBarWrapper.prototype.doUpArrowClick = function () {
        var newScrollOffset = this.scrollOffset - 24;
        newScrollOffset = Math.max(newScrollOffset, 0);
        this.scrollOffset = newScrollOffset;
    };
    ScrollBarWrapper.prototype.isDownArrowClick = function (relativePos) {
        return (relativePos + IScrollBar.INST.UP_DOWN_ARROW_SIZE > this.outerScrollBarHeight);
    };
    ScrollBarWrapper.prototype.doDownArrowClick = function () {
        var newScrollOffset = this.scrollOffset + 24;
        var max = this.totalScrollableContentHeight - this.outerScrollBarHeight;
        newScrollOffset = Math.min(newScrollOffset, max);
        this.scrollOffset = newScrollOffset;
    };
    /**
     * @return -1 if the click is above the thumb, 0 if on the thumb, +1 if below the thumb
     * That is, -1 means page up, +1 means page down, 0 means do not move
     * @param clickPosition: page-relative Y coordinate of a mouse click
     */
    ScrollBarWrapper.prototype.isEventAboveBelowOrOnThumb = function (clickPosition) {
        var thumbTop = this.scrollBarThumb.getPosition().y;
        var thumbBottom = thumbTop + this.scrollBarThumbHeight;
        if (clickPosition < thumbTop)
            return -1;
        if (clickPosition < thumbBottom)
            return 0;
        return 1;
    };
    ScrollBarWrapper.prototype.isDragging = function (clickPosition) {
        return clickPosition != this.lastMousePosSinceDragStart;
    };
    ScrollBarWrapper.prototype.setAutoAdjustWindow = function (b) {
        this.autoAdjustWindow = b;
    };
    ScrollBarWrapper.prototype.setAllowWindowScroll = function (b) {
        this.allowWindowScroll = b;
    };
    ScrollBarWrapper.prototype.setDesiredVerticalOffset = function (offset) {
        this.desiredVerticalOffset = offset;
    };
    ScrollBarWrapper.prototype.handleScroll = function (ev) {
        var currentY = Viewport.scrollY();
        var topY = this.innerScrollBarTop - this.desiredVerticalOffset;
        var bottomY = this.innerScrollBarTop + this.innerScrollBarHeight - Viewport.windowHeight();
        var targetY = Math.floor((topY + bottomY) / 2);
        if (currentY != targetY && !Viewport.isScrolling()) {
            if (ev.wheel < 0 &&
                this.innerScrollBarTop + this.innerScrollBarHeight > currentY + Viewport.windowHeight() + 10) {
                this.timeOfLastRejectedWheel = new Date().getTime();
                return !this.allowWindowScroll;
            }
            if (ev.wheel > 0 &&
                this.innerScrollBarTop - this.desiredVerticalOffset < currentY - 2) {
                this.timeOfLastRejectedWheel = new Date().getTime();
                return !this.allowWindowScroll;
            }
        }
        var newScrollOffset = this.scrollOffset - (ev.wheel * IScrollBar.INST.WHEEL_SPEED);
        this.scrollOffset = newScrollOffset;
        // this may reset scrollOffset in some way
        this.updateFromScrollOffset();
        // if we haven't reset scrollOffset... then prevent defaults
        if (this.autoAdjustWindow) {
            clearTimeout(this.mouseWheelTimer);
            if (this.scrollOffset == newScrollOffset || Viewport.isScrolling()) {
                if (new Date().getTime() - this.timeOfLastRejectedWheel < 100) {
                    scrollTo(0, targetY);
                    setTimeout(function () {
                        scrollTo(0, targetY);
                    }, 10);
                }
                else {
                    this.mouseWheelTimer = setTimeout(this.boundLockToTop, 100);
                }
                return true;
            }
            else {
                return !this.allowWindowScroll;
            }
        }
        else {
            if (this.scrollOffset == newScrollOffset || Viewport.isScrolling()) {
                return true;
            }
            else {
                return !this.allowWindowScroll;
            }
        }
    };
    ScrollBarWrapper.prototype.collides = function (pageX, pageY) {
        if (this.y == null) {
            this.y = q$(this.e).getTop();
            this.x = q$(this.e).getLeft();
            this.size = q$(this.e).getSize();
        }
        return ((this.x < pageX) && (pageX < this.x + this.size.x) &&
            (this.y < pageY) && (pageY < this.y + this.size.y));
    };
    ScrollBarWrapper.prototype.readjust = function () {
        this.y = null;
        this.x = null;
        this.size = null;
        this.outerScrollBarHeight = q$(this.e).getSize().y;
        this.innerScrollBarHeight = this.outerScrollBarHeight - 2 * (IScrollBar.INST.UP_DOWN_ARROW_SIZE);
        this.totalScrollableContentHeight = this.scrollContents.getScrollSize().y;
        // avoid divide by zero if max is zero
        if (this.totalScrollableContentHeight == 0)
            this.totalScrollableContentHeight = this.innerScrollBarHeight + 1;
        var maxHeight = parseInt(q$(this.e).getStyle('max-height'));
        if (isNaN(maxHeight))
            maxHeight = 0;
        if (maxHeight > this.totalScrollableContentHeight || this.innerScrollBarHeight < this.totalScrollableContentHeight) {
            this.outerScrollBarHeight = Math.max(this.outerScrollBarHeight, Math.min(maxHeight, this.totalScrollableContentHeight));
            this.innerScrollBarHeight = this.outerScrollBarHeight - 2 * IScrollBar.INST.UP_DOWN_ARROW_SIZE;
        }
        this.outerScrollBarTop = q$(this.scrollBar).getTop();
        this.innerScrollBarTop = this.outerScrollBarTop + IScrollBar.INST.UP_DOWN_ARROW_SIZE;
        this.scrollOffset = this.scrollContents.getScroll().y;
        this.scrollContents.setStyle('height', this.outerScrollBarHeight);
        this.scrollBar.setStyle('height', this.outerScrollBarHeight);
        this.scrollBarThumbHeight = Math.min(Math.max((this.outerScrollBarHeight / this.totalScrollableContentHeight) * this.outerScrollBarHeight, IScrollBar.INST.HANDLE_HEIGHT), (this.outerScrollBarHeight / 2));
        this.scrollBarThumb.setStyle('height', this.scrollBarThumbHeight);
        this.scrollBarThumb.setStyle('top', this.innerScrollBarTop + 'px');
        if (this.outerScrollBarHeight >= this.totalScrollableContentHeight) {
            this.e.addClass('hideScrollBar'); //setStyle('opacity', 1);
        }
        else {
            this.e.removeClass('hideScrollBar'); //setStyle('opacity', 0);
        }
        this.updateFromScrollOffset();
        this.updateNewTicks();
    };
    ScrollBarWrapper.prototype.findNewTicks = function () {
        var newElements = this.scrollContents.getElements(".new");
        newElements.each(function (newElement) {
            if (this.newTicks[newElement.id] == null) {
                var newTick = document.createElement('div');
                q$(newTick).addClass('newTick');
                newTick.elementY = q$(newElement).getTop() - this.scrollOffset - this.innerScrollBarTop;
                this.scrollBar.insertBefore(newTick, this.scrollBarThumb);
                this.newTicks[newElement.id] = newTick;
            }
        }.bind(this));
        this.updateNewTicks();
    };
    ScrollBarWrapper.prototype.getMaxScroll = function () {
        return this.totalScrollableContentHeight - this.outerScrollBarHeight;
    };
    ScrollBarWrapper.prototype.lockToTop = function () {
        this.outerScrollBarTop = q$(this.scrollBar).getTop();
        this.innerScrollBarTop = this.outerScrollBarTop + IScrollBar.INST.UP_DOWN_ARROW_SIZE;
        var topY = this.outerScrollBarTop - this.desiredVerticalOffset;
        var bottomY = this.outerScrollBarTop + this.outerScrollBarHeight - Viewport.windowHeight();
        var targetY = Math.floor((topY + bottomY) / 2);
        if (this.outerScrollBarHeight + this.desiredVerticalOffset < Viewport.windowHeight()) {
            Viewport.scrollTo(targetY);
        }
    };
    ScrollBarWrapper.prototype.updateNewTicks = function () {
        var newTick;
        for (newTick in this.newTicks) {
            if (!this.newTicks.hasOwnProperty(newTick))
                return;
            var t = newTick.elementY;
            var tt = (t / (this.totalScrollableContentHeight - this.innerScrollBarHeight) * (this.innerScrollBarHeight - this.scrollBarThumbHeight));
            var newtop = tt - 3 + (this.scrollBarThumbHeight / 2);
            newTick.setStyle('top', newtop);
        }
    };
    ScrollBarWrapper.prototype.updateFromScrollOffset = function () {
        var max = this.getMaxScroll();
        if (Math.abs(this.totalScrollableContentHeight - this.innerScrollBarHeight) > 5) {
            if (this.scrollOffset < 0)
                this.scrollOffset = 0;
            if (this.scrollOffset > max)
                this.scrollOffset = max;
            this.scrollContents.scrollTo(0, this.scrollOffset);
            var fractionOfTheWayFromTopToBottom = (!max ? 0 : this.scrollOffset / max);
            var totalRoomForScrollBarThumbToLiveIn = this.innerScrollBarHeight - this.scrollBarThumbHeight;
            var scrollBarThumbPosition = fractionOfTheWayFromTopToBottom * totalRoomForScrollBarThumbToLiveIn;
            this.scrollBarThumb.setStyle('top', scrollBarThumbPosition + IScrollBar.INST.UP_DOWN_ARROW_SIZE);
            Common.cshow(this.scrollBarThumb);
        }
        else {
            this.scrollOffset = 0;
            Common.chide(this.scrollBarThumb);
        }
    };
    ScrollBarWrapper.prototype.scrollToBottom = function () {
        this.scrollOffset = this.getMaxScroll() - 5;
        this.updateFromScrollOffset();
    };
    return ScrollBarWrapper;
}());

//include "Viewport.js"
//include "feature/DelayedBackground.js"



// MoreDialog.js

//xnclude "DialogUtils.js"
//xnclude "QScroller.js"
//xnclude "Viewport.js"
/// <reference path="DialogUtils.ts" />
/// <reference path="QScroller.ts" />
/// <reference path="Viewport.ts" />
var MoreDialog = (function () {
    function MoreDialog() {
    }
    MoreDialog.Show = function (e, url, title, onload) {
        MoreDialog._targetElement = e;
        q$('moreDialogContents').innerHTML = "";
        Common.cshow('moreDialog');
        q$('moreDialogTitle').innerHTML = (title) ? title : "";
        var moreDialogBodyElt = q$('moreDialogBody');
        if (moreDialogBodyElt)
            moreDialogBodyElt.addClass('waiting');
        MoreDialog.HandleTopicDialogResize();
        window.addEvent('resize', MoreDialog.HandleTopicDialogResize);
        window.addEvent('scroll', MoreDialog.Close);
        if (!MoreDialog._scrollBarWrapper) {
            MoreDialog._scrollBarWrapper = new ScrollBarWrapper(moreDialogBodyElt);
            MoreDialog._scrollBarWrapper.setAutoAdjustWindow(false);
            MoreDialog._scrollBarWrapper.setAllowWindowScroll(false);
        }
        Ajax.getText(url, function (text) {
            q$('moreDialogContents').innerHTML = text;
            MoreDialog.HandleTopicDialogResize();
            var moreDialogBodyElt = q$('moreDialogBody');
            if (moreDialogBodyElt)
                moreDialogBodyElt.removeClass('waiting');
            DelayedBackground.loadAllImages(moreDialogBodyElt);
            setTimeout(function () {
                if (MoreDialog._scrollBarWrapper) {
                    MoreDialog._scrollBarWrapper.readjust();
                }
                if (onload)
                    onload();
            }, 100);
        });
        q$(e).addClass("popupBeingShown");
    };
    MoreDialog.Close = function () {
        window.removeEvent('resize', MoreDialog.HandleTopicDialogResize);
        window.removeEvent('scroll', MoreDialog.Close);
        Common.chide('moreDialog');
        q$(MoreDialog._targetElement).removeClass("popupBeingShown");
        if (MoreDialog._scrollBarWrapper)
            MoreDialog._scrollBarWrapper.readjust();
    };
    MoreDialog.HandleTopicDialogResize = function () {
        q$('moreDialog').setStyle("top", Viewport.scrollY());
        var dialogHeight = Viewport.windowHeight() - MoreDialog.PAGE_PADDING * 2;
        if (dialogHeight < 300)
            dialogHeight = 300;
        var contentsHeight = q$('moreDialogContents').getSize().y;
        if (contentsHeight < 100)
            contentsHeight = 100;
        if (contentsHeight < dialogHeight)
            dialogHeight = contentsHeight;
        var windowWidth = Viewport.windowWidth();
        var moreDialogBody = q$('moreDialogBody');
        moreDialogBody.setStyle('height', dialogHeight + "px");
        moreDialogBody.setStyle('max-height', dialogHeight + "px");
        var targetTop = q$(MoreDialog._targetElement).getTop();
        var innerDialog = q$('moreDialogInnerDialog');
        var innerDialogSize = innerDialog.getSize();
        var desiredWidth = innerDialogSize.x;
        var desiredHeight = innerDialogSize.y;
        var desiredTop = (Viewport.windowHeight() - desiredHeight) / 2;
        if (dialogHeight == contentsHeight)
            desiredTop = targetTop - Viewport.scrollY() - MoreDialog.PAGE_PADDING;
        if (desiredTop + dialogHeight + MoreDialog.PAGE_PADDING > Viewport.windowHeight())
            desiredTop = Viewport.windowHeight() - dialogHeight - MoreDialog.PAGE_PADDING;
        if (desiredTop < 20)
            desiredTop = 20;
        var targetLeft = MoreDialog._targetElement.getLeft() - MoreDialog.PADDING;
        var targetRight = targetLeft + q$(MoreDialog._targetElement).getSize().x + MoreDialog.PADDING * 2;
        var desiredLeft = (windowWidth - desiredWidth) / 2;
        var moreDialogArrow = q$('moreDialogArrow');
        var arrowTop = (targetTop + (q$(MoreDialog._targetElement).getSize().y / 2) - Viewport.scrollY() - MoreDialog.ARROW_SIZE_Y);
        if (arrowTop < MoreDialog.PAGE_PADDING || arrowTop > Viewport.windowHeight() - MoreDialog.PAGE_PADDING)
            arrowTop = -1000;
        var arrowElt = q$(moreDialogArrow);
        arrowElt.setStyle('top', arrowTop + "px");
        var leftStyleVal = 0;
        if (windowWidth - targetRight > targetLeft) {
            desiredLeft = targetRight;
            moreDialogArrow.className = 'moreDialogLeftArrow';
            leftStyleVal = desiredLeft + 1 - MoreDialog.PADDING - MoreDialog.ARROW_SIZE_X + (MoreDialog.PADDING - MoreDialog.ARROW_SIZE_X);
        }
        else {
            desiredLeft = targetLeft - MoreDialog.WIDTH;
            moreDialogArrow.className = 'moreDialogRightArrow';
            leftStyleVal = desiredLeft - 1 + MoreDialog.WIDTH + MoreDialog.PADDING - MoreDialog.ARROW_SIZE_X - (MoreDialog.PADDING - MoreDialog.ARROW_SIZE_X);
        }
        arrowElt.setStyle('left', leftStyleVal + "px");
        innerDialog.setStyle('left', desiredLeft + 'px');
        innerDialog.setStyle('top', desiredTop + 'px');
        // resize background to stick to the sides
        var bg = q$('moreDialogBackground');
        if (bg) {
            DialogUtils.resizeOpaqueBackground(bg);
        }
        if (MoreDialog._scrollBarWrapper)
            MoreDialog._scrollBarWrapper.readjust();
    };
    MoreDialog.WIDTH = 450;
    MoreDialog.PAGE_PADDING = 40;
    MoreDialog.PADDING = 25;
    MoreDialog.ARROW_SIZE_X = 15;
    MoreDialog.ARROW_SIZE_Y = 30;
    MoreDialog._targetElement = null;
    MoreDialog._scrollBarWrapper = null;
    return MoreDialog;
}());

//include "DialogUtils.js"
//include "QScroller.js"
//include "Viewport.js"



// AfterDfLoadEvents.js

var AfterDfLoadEventsClass = (function () {
    function AfterDfLoadEventsClass() {
        this.hasNotified = false;
        this.listeners = [];
    }
    AfterDfLoadEventsClass.prototype.register = function (fn) {
        // register for later execution until notifications have been made.
        this.listeners.push(fn);
        if (this.hasNotified) {
            try {
                fn();
            }
            catch (e) {
            }
        }
    };
    AfterDfLoadEventsClass.prototype.renotifyRegisteredWidgets = function () {
        // run the notifies, even if they've already been run
        this._notify();
    };
    AfterDfLoadEventsClass.prototype.notifyRegisteredWidgets = function () {
        // Maybe do this form only once? I didn't do this now because we might
        // need the behavior.
        this._notify();
    };
    AfterDfLoadEventsClass.prototype._notify = function () {
        // Common.addDebugStr("AfterDfLoadEvents._notify len= " + this.listeners.length);
        this.hasNotified = true;
        for (var i = 0; i < this.listeners.length; i++) {
            var lstnr = this.listeners[i];
            try {
                lstnr.call();
            }
            catch (e) {
                var msg = "EXC AfterDfLoadEvents.notify =" + e +
                    " i=" + i + " " + lstnr.toString();
                Common.addDebugStr(msg);
            }
        }
    };
    return AfterDfLoadEventsClass;
}());
var AfterDfLoadEvents = new AfterDfLoadEventsClass();




// StringBuilder.js

//****************************************************************************************************
// StringBuilder Class
//****************************************************************************************************
var StringBuilder = (function () {
    function StringBuilder(value) {
        this.strings = [""];
        if (value) {
            this.Append(value);
        }
    }
    // Appends the given value to the end of this instance.
    StringBuilder.prototype.Append = function (value) {
        if (value) {
            this.strings.push(value);
        }
    };
    // Clears the string buffer
    StringBuilder.prototype.Clear = function () {
        this.strings.length = 1;
    };
    // Converts this instance to a String.
    StringBuilder.prototype.sbToString = function () {
        return this.strings.join("");
    };
    return StringBuilder;
}());




// Utf8.js

var Utf8 = (function () {
    function Utf8() {
    }
    Utf8.encode = function (str) {
        str = str.replace(/\r\n/g, "\n");
        var utftext = "";
        for (var n = 0; n < str.length; n++) {
            var c = str.charCodeAt(n);
            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if ((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
        }
        return utftext;
    };
    // public method for url decoding
    Utf8.decode = function (utftext) {
        var str = "";
        var i = 0;
        while (i < utftext.length) {
            var c = utftext.charCodeAt(i);
            if (c < 128) {
                str += String.fromCharCode(c);
                i++;
            }
            else if ((c > 191) && (c < 224)) {
                var c2 = utftext.charCodeAt(i + 1);
                str += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else {
                var c2 = utftext.charCodeAt(i + 1);
                var c3 = utftext.charCodeAt(i + 2);
                str += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return str;
    };
    return Utf8;
}());




// ScreenDoor.js

var ScreenDoor = (function () {
    function ScreenDoor() {
    }
    ScreenDoor.To = function (i) {
        // double it up to prevent users from easily being able to rotate to new values
        var key = i + "" + i;
        return ScreenDoor.FromDecimal(parseInt(key));
    };
    ScreenDoor.From = function (s) {
        if (s == null)
            return null;
        var s_as_i = ScreenDoor.ToDecimal(s);
        s = s_as_i + "";
        var length = s.length;
        if (length % 2 != 0) {
            return null;
        }
        var firstHalf = s.substr(0, length / 2);
        var secondHalf = s.substr(length / 2, length / 2);
        if (firstHalf != secondHalf) {
            return null;
        }
        return parseInt(firstHalf);
    };
    ScreenDoor.FromDecimal = function (i) {
        var base = ScreenDoor.key.length;
        var result = "";
        do {
            var remainder = i % base;
            result = ScreenDoor.key.substr(remainder, 1) + result;
            i = Math.floor(i / base);
        } while (i > 0);
        return result;
    };
    ScreenDoor.ToDecimal = function (s) {
        var base = ScreenDoor.key.length;
        var result = 0;
        for (var i = 0; i < s.length; i++) {
            result += ScreenDoor.key.indexOf(s.substr(s.length - i - 1, 1)) * Math.pow(base, i);
        }
        return result;
    };
    // unscramble Quantia name (a sequence of alphanumeric symbols, dots and underscores)
    ScreenDoor.unscrambleScreenName = function (sname) {
        var result = '';
        for (var i = 0; i < sname.length; ++i) {
            var c = sname.charAt(i);
            var index = ScreenDoor.scrambledNameSymbols.indexOf(c);
            if (index >= 0) {
                result = result + ScreenDoor.nameSymbols.charAt(index);
            }
        }
        return result;
    };
    ScreenDoor.key = "aywdbzgecjhfnkirpmusqxvt";
    ScreenDoor.nameSymbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.";
    ScreenDoor.scrambledNameSymbols = "mr7vg3.nx9ci04ue2d1b6qfaltmr7vg3.nx9ci04ue2d1b6qfalt8pkozj_ys5wh";
    return ScreenDoor;
}());




// JSONDataContainer.js

/// <reference path="mootools.d.ts" />
/// <reference path="Common.d.ts" />
var JSONDataContainer = (function () {
    function JSONDataContainer(src) {
        /*
         * Constructor can receive either a string containing a valid json object representation
         * or an already-populated object... if this were java, we'd have
         * two constructors
         *
         * If a string, parse it here
         */
        if (typeof (src) === "string") {
            this.privateData = Common.jsonParse(src);
        }
        else {
            this.privateData = src;
        }
    }
    JSONDataContainer.prototype.stringify = function () {
        return JSON.stringify(this.privateData);
    };
    JSONDataContainer.prototype.getValueIfExists = function () {
        var pathToValue = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            pathToValue[_i] = arguments[_i];
        }
        var len = pathToValue.length;
        var value = this.privateData;
        for (var n = 0; n < len; ++n) {
            var nthArg = pathToValue[n];
            if (typeof value[nthArg] === 'undefined') {
                return null;
            }
            value = value[nthArg];
        }
        return value;
    };
    // public getStringValue(...pathToValue:string[]):string {
    //     let value = this.getValueIfExists.apply(this, pathToValue);
    //     if (!value)
    //         return null;
    //     if (typeof value != "string")
    //         return null;
    //     return value.toString();
    // }
    JSONDataContainer.prototype.getNumericValue = function () {
        var pathToValue = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            pathToValue[_i] = arguments[_i];
        }
        var value = this.getValueIfExists.apply(this, pathToValue);
        return (!value) ? 0 : Number(value);
    };
    JSONDataContainer.prototype.getBooleanValue = function () {
        var pathToValue = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            pathToValue[_i] = arguments[_i];
        }
        var value = this.getValueIfExists.apply(this, pathToValue);
        return (!!value);
    };
    JSONDataContainer.prototype.getValueAsArray = function () {
        var pathToValue = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            pathToValue[_i] = arguments[_i];
        }
        var len = pathToValue.length;
        var value = this.privateData;
        for (var n = 0; n < len; ++n) {
            var nthArg = pathToValue[n];
            if (typeof value[nthArg] === 'undefined') {
                return null;
            }
            value = value[nthArg];
        }
        if (!Array.isArray(value)) {
            // convert non-array to an array.
            value = [value];
        }
        return value;
    };
    return JSONDataContainer;
}());
// perhaps should be moved to a more generic source file.
Array.isArray || (Array.isArray = function (a) {
    // is not the string '[object Array]' and
    return '' + a !== a &&
        // test with Object.prototype.toString
        {}.toString.call(a) == '[object Array]';
});




// AddressBook.js

//xnclude "JSONDataContainer.js"
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
/// <reference path="JSONDataContainer.ts" />
var AddressBook = (function (_super) {
    __extends(AddressBook, _super);
    function AddressBook(date) {
        return _super.call(this, date) || this;
    }
    AddressBook.prototype.getStatus = function () {
        return this.getValueIfExists('status');
    };
    AddressBook.prototype.getAddresses = function () {
        return this.getValueAsArray("addresses");
    };
    return AddressBook;
}(JSONDataContainer));

//include "JSONDataContainer.js"



// PeerMessageComposer.js

//xnclude "Utf8.js"
//xnclude "PeerMsgComposerLauncher.js"
//xnclude "ScreenDoor.js"
//xnclude DfRequest_PeerMsg.js"
//xnclude "AddressBook.js"
/// <reference path="Common.d.ts" />
/// <reference path="Mootools.d.ts" />
/// <reference path="Ajax.d.ts" />
/// <reference path="ScreenDoor.ts" />
/// <reference path="Utf8.ts" />
/// <reference path="PeerMsgComposerLauncher.ts" />
PeerMsgComposerLauncher;
var PeerMessageComposer = (function () {
    function PeerMessageComposer(args) {
        this.newEmailMessageAddresses = [];
        this.prepopulatedEntry = "";
        this.currentAB = [];
        this.isLocked = false;
        this.focusTimer = null;
        this.toggleTime = 0;
        this.presetTo = "";
        this.presetReferralDfid = 0;
        this.presetReferralURI = '';
        this.presetReferralDfTitle = "";
        this.boundDialogResizeFunc = null;
        this.dfRequest = new DfRequest_PeerMsg(args);
        this.newEmailMessageAddresses = [];
        this.prepopulatedEntry = "";
        this.currentAB = [];
        this.isLocked = false;
        this.focusTimer = null;
        this.toggleTime = 0;
        this.presetTo = "";
        this.presetReferralDfid = 0;
        this.presetReferralURI = '';
        this.presetReferralDfTitle = "";
        this.boundDialogResizeFunc = null;
        if (args) {
            if (args.to)
                this.presetTo = args.to;
            if (args.refuri)
                this.presetReferralURI = args.refuri;
            if (args.refdfid)
                this.presetReferralDfid = args.refdfid;
            if (args.reftitle)
                this.presetReferralDfTitle = args.reftitle;
        }
        // some initialization requires the DOM
        doOnPageReady(this.onPageReady.bind(this));
    }
    PeerMessageComposer.prototype.onPageReady = function () {
        if (Common.isWeb())
            gQCredentials.loadCachedCreds();
        try {
            var pubElt = q$('publishLink');
            if (pubElt) {
                pubElt.onclick = this.publish.bind(this);
            }
        }
        catch (e) {
            alert("PeerMessageComposer.onPageReady " + e.message);
        }
        var boundFunc = this.updatePublishButton.bind(this);
        var bodyElt = q$('emailBody');
        bodyElt.onchange = boundFunc;
        bodyElt.onkeyup = boundFunc;
        bodyElt.onpaste = boundFunc;
        var subjElt = q$('emailSubject');
        subjElt.onchange = boundFunc;
        subjElt.onkeyup = boundFunc;
        subjElt.onpaste = boundFunc;
        document.onclick = boundFunc;
        this.submissionPending = false;
        this.prepopulatedEntry = this.getPrepopulatedEntry();
        this.currentAB = this.getCurrentABList();
        this.setupArrowHandler();
        this.addUploadDiv();
        var pwElt = q$('composePassword');
        if (pwElt) {
            pwElt.addEvent("keyup", this.passwordEntered.bind(this));
        }
        var closeConfElt = q$('closeConfirmationButton');
        closeConfElt.onclick = this.dialogCloseOnly.bind(this);
        this.updatePublishButton();
    };
    PeerMessageComposer.prototype.setupArrowHandler = function () {
        var btn = q$('address_book_button');
        btn.addEvent('click', this.toggleArrow.bind(this));
        var inputElement = $$('#peerMessageRecipients_chzn input')[0];
        if (inputElement) {
            inputElement.addEvent('focus', this.forceArrowUp.bind(this));
        }
    };
    PeerMessageComposer.prototype.testFocus = function () {
        var toField = q$('peerMessageRecipients');
        if (toField.chosen.active_field) {
            this.focusTimer = setTimeout(this.testFocus.bind(this), 100);
        }
        else {
            this.focusTimer = null;
            this.forceArrowDown();
        }
    };
    PeerMessageComposer.prototype.forceArrowUp = function () {
        this.toggleTime = (new Date()).getTime();
        var btn = q$('address_book_button');
        btn.addClass('flipped');
        if (!this.focusTimer) {
            this.focusTimer = setTimeout(this.testFocus.bind(this), 100);
        }
    };
    PeerMessageComposer.prototype.forceArrowDown = function () {
        this.toggleTime = (new Date()).getTime();
        var btn = q$('address_book_button');
        btn.removeClass('flipped');
        if (this.focusTimer) {
            clearTimeout(this.focusTimer);
            this.focusTimer = null;
        }
    };
    PeerMessageComposer.prototype.toggleArrow = function () {
        var now = (new Date()).getTime();
        // ignore double-click
        if (now - this.toggleTime > 500) {
            var btn = q$('address_book_button');
            var toField = q$('peerMessageRecipients');
            if (btn.hasClass('flipped')) {
                this.forceArrowDown();
            }
            else {
                toField.chosen.container_click();
                this.forceArrowUp();
            }
        }
    };
    PeerMessageComposer.prototype.getCurrentABList = function () {
        var results = [];
        var dm = q$('peerMessageRecipients');
        if (!dm) {
            return (results);
        }
        for (var i = 0; i < dm.options.length; i++) {
            results.push(dm.options[i]);
        }
        return results;
    };
    PeerMessageComposer.prototype.getAddressBookViaAjax = function () {
        var url = QSettings.buildUrlCmd("getreqidanddaddressbook");
        url = url + "&;ssl";
        var self = this;
        Ajax.getText(url, function (text) {
            self.fillInAddressBook(text);
        });
    };
    PeerMessageComposer.prototype.makeABOptionElt = function (entry) {
        return '<option value="' + entry.optionValue + '" data-inpab="' + entry.data_inPAB + '">' + entry.email + '</option>';
    };
    PeerMessageComposer.prototype.fillInAddressBook = function (jsonData) {
        var addressBook, addresses = null, i, newopts = [];
        var addrBook = new AddressBook(jsonData);
        if (addrBook.getStatus() !== 'ok') {
            alert(addrBook.getStatus());
        }
        else {
            addressBook = q$('peerMessageRecipients');
            addresses = addrBook.getAddresses();
            for (i = 0; i < addresses.length; ++i) {
                var newOption = this.makeABOptionElt(addresses[i]);
                newopts.push(newOption);
            }
            // update the DOM only once
            addressBook.innerHTML = newopts.join('\n');
            var c = $$(".chzn-select");
            c.chosen();
            this.dfRequest.requestId = addrBook.getValueIfExists('reqid');
            this.currentAB = this.getCurrentABList();
        }
    };
    PeerMessageComposer.prototype.getPrepopulatedEntry = function () {
        var dm = q$('peerMessageRecipients');
        var entry = "";
        if (dm) {
            for (var i = 0; i < dm.options.length; i++) {
                var option = dm.options[i];
                if (option.value == this.presetTo)
                    entry = option;
            }
        }
        return entry;
    };
    PeerMessageComposer.prototype.areAllIputFieldsEmpty = function () {
        if (!q$('peerMessageRecipients')) {
            return false;
        }
        var aryEmailAddrs = this.getDiscussionMembers();
        if (aryEmailAddrs != null && aryEmailAddrs.length > 0) {
            return false;
        }
        var s = q$('emailSubject');
        var title = s.value.trim();
        if (!(title == '')) {
            return false;
        }
        var msgcontent = q$('emailBody').value.trim();
        if (!(msgcontent == '')) {
            return false;
        }
        var attachments = $$(".attachment");
        for (var i = 0; i < attachments.length; i++) {
            if (!attachments[i].hasClass('cHidden')) {
                return false;
            }
        }
        return true;
    };
    PeerMessageComposer.prototype.dialogCloseWithConfirmation = function () {
        if (!this.areAllIputFieldsEmpty()) {
            this.showPopupDialog('confirmBox', true);
        }
        else {
            this.dialogCloseOnly();
        }
    };
    PeerMessageComposer.prototype.mobileDialogCloseWithConfirmation = function () {
        if (!this.areAllIputFieldsEmpty()) {
            this.mobileShowConfirmBox();
        }
        else {
            this.dialogCloseOnly();
        }
    };
    PeerMessageComposer.prototype.mobileShowConfirmBox = function () {
        var confirmbox = q$('confirmBox');
        var confirmbox_bckgrnd = q$('dialogBackground_confirmBox');
        if (confirmbox && confirmbox_bckgrnd) {
            Common.cshow(confirmbox);
            displayMobileConfirmboxBackground(confirmbox.offsetTop, confirmbox.offsetLeft, confirmbox, confirmbox_bckgrnd);
        }
    };
    PeerMessageComposer.prototype.confirmedClose = function (bCloseMessage) {
        this.showPopupDialog('confirmBox', false);
        if (bCloseMessage) {
            this.dialogCloseOnly();
        }
    };
    PeerMessageComposer.prototype.dialogClose = function () {
        var isInbox = this.isInInbox();
        this.cleanUpBeforeClose();
        // A peer message can be embedded in a QModalLite dlg or not
        // if so, close it this way
        if (typeof QModalLite != 'undefined') {
            PeerMessageInbox.closingDialog();
            QModalLite.hideModal(q$('emailMessageInnerContainer'), Common.returnTrue);
            if (isInbox) {
                document.location.reload();
            }
        }
        else {
            QModalDialog.requestDlgClose('/home/inbox');
        }
    };
    PeerMessageComposer.prototype.dialogCloseOnly = function () {
        var isInbox = this.isInInbox();
        this.cleanUpBeforeClose();
        // A peer message can be embedded in a QModalLite dlg or not
        // if so, close it this way
        if (typeof QModalLite != 'undefined') {
            PeerMessageInbox.closingDialog();
            QModalLite.hideModal(q$('emailMessageInnerContainer'), Common.returnTrue);
            if (isInbox) {
                document.location.reload();
            }
        }
        else {
            QModalDialog.requestDlgClose();
        }
    };
    PeerMessageComposer.prototype.cleanUpBeforeClose = function () {
        Common.chide('emailConfirmation');
        q$('emailSubject').value = "";
        q$('emailBody').value = "";
        this.cleanUpRecipients();
        this.cleanupAttachments();
    };
    PeerMessageComposer.prototype.cleanUpRecipients = function () {
        var searchchoices = q$('emailMessages').getElements('ul.chzn-choices');
        if (searchchoices) {
            searchchoices.getElements('li.search-choice')[0].destroy();
        }
        var dm = q$('peerMessageRecipients');
        if (dm) {
            for (var i = 0; i < dm.options.length; i++) {
                dm.options[i].selected = false;
            }
        }
    };
    PeerMessageComposer.prototype.cleanupAttachments = function () {
        var attachmentsNode = q$('attachments');
        if (attachmentsNode) {
            while (attachmentsNode.firstChild) {
                attachmentsNode.removeChild(attachmentsNode.firstChild);
            }
        }
    };
    PeerMessageComposer.prototype.toggleLock = function () {
        var toggleElt = q$('toggleLockLink');
        if (!this.isLocked) {
            toggleElt.removeClass('lockArea');
            toggleElt.addClass('unlockArea');
            toggleElt.innerHTML = QSTR.unlockMessage;
            this.dfRequest.requiresInactivityTimeout = true;
        }
        else {
            toggleElt.removeClass('unlockArea');
            toggleElt.addClass('lockArea');
            toggleElt.innerHTML = QSTR.lockMessage;
            this.dfRequest.requiresInactivityTimeout = false;
        }
        this.isLocked = !this.isLocked;
    };
    PeerMessageComposer.prototype.isInInbox = function () {
        var p = document.location.pathname;
        var istr = '/inbox';
        var ilen = istr.length;
        // does the path end with '/inbox'?
        if (p.indexOf('/inbox') + ilen == p.length) {
            return true;
        }
        // does the argument portion of the url contain this?
        return (document.location.search.indexOf("isInInbox=true") > -1);
    };
    PeerMessageComposer.prototype.addUploadDiv = function () {
        var uploadLink = q$('fakeUploadLink');
        if (!uploadLink)
            return;
        if (this.dfRequest == null)
            return;
        var qAuthCookie = new QAuthCookie(readCookie("auth"));
        var uploadUrl = "/q-submissions?cmd=newFile&key=" +
            gQCredentials.ScreenDoorName + "_" + this.dfRequest.requestId + "_" + 0 +
            "&user=" + qAuthCookie._userScreenDoor +
            "&pass=" + qAuthCookie._creds +
            "&reqid=" + this.dfRequest.requestId +
            "&requiresEncryption=true" +
            "&ec=0";
        var u = new UploadAttachments({
            addUrlElement: q$('attachUrl'),
            urlInputElement: q$('newUrl'),
            submitUrlElement: q$('submitNewUrl'),
            requiresEncryption: true,
            url: uploadUrl,
            uploadPlaceholderSpanId: 'uploadPlaceholder',
            fakeUploadLinkElement: uploadLink,
            attachmentListElement: q$('attachments'),
            isPeerMessage: true
        });
        this.dfRequest.SetAttachments(u);
    };
    PeerMessageComposer.prototype.disablePost = function () {
        this.submissionPending = true;
        this.updatePublishButton();
    };
    PeerMessageComposer.prototype.enablePost = function () {
        this.submissionPending = false;
        this.updatePublishButton();
    };
    PeerMessageComposer.prototype.returnFocusToTop = function () {
        var item = q$('peerMessageRecipients_chzn');
        if (item) {
            var inputField = item.getElement('input');
            if (inputField)
                inputField.focus();
        }
    };
    PeerMessageComposer.prototype.getDiscussionMembers = function () {
        var dm = q$('peerMessageRecipients');
        var results = [];
        if (dm) {
            for (var i = 0; i < dm.options.length; i++) {
                var option = dm.options[i];
                if (option.value == '')
                    continue;
                if (option.selected)
                    results.push(option.value);
            }
        }
        return results;
    };
    PeerMessageComposer.prototype.validate = function () {
        var title = q$('emailSubject').get('value').trim();
        if (title == '' || title == QSTR.newDiscussionEnterASubject) {
            return (QSTR.postQuestionNoTitle);
        }
        var userData = q$('emailBody').get('value').trim();
        if (userData == '') {
            return (QSTR.postQuestionNoText);
        }
        if (userData.length > 64000) {
            return (sprintf(QSTR.postQuestionTooLong, userData.length));
        }
        if (q$('peerMessageRecipients')) {
            // this element OUGHT to be defined always
            var aryMembers = this.getDiscussionMembers();
            if (aryMembers == null || aryMembers.length == 0) {
                return (QSTR.postQuestionNoMembers);
            }
            if (PeerMessageComposer.containsInvalidEmail()) {
                return QSTR.peerMessageInvalidRecipient;
            }
        }
        return null;
    };
    PeerMessageComposer.prototype.passwordEntered = function (e) {
        var keyPressed = e.key;
        var composeElt = q$('composePassword');
        if (keyPressed == 'enter') {
            if (composeElt.value == '') {
                composeElt.focus();
                return;
            }
            this.confirmComposePassword();
        }
        else {
            q$('confirmComposePassword').toggleClass('disabledButton', (composeElt.value == ''));
        }
    };
    PeerMessageComposer.prototype.checkInactivityBeforeSubmit = function () {
        var self = this;
        ActivityMonitor.requestActivityLease(function (act) {
            if (act) {
                self.showComposePasswordPrompt(false);
                self.dfRequest.submit(self.onSubmitSuccess.bind(self), self.onSubmitFailure.bind(self));
            }
            else {
                self.showComposePasswordPrompt(true);
            }
            // otherwise already expired on the server
        }, function () {
            self.showComposePasswordPrompt(true);
        });
    };
    PeerMessageComposer.prototype.showComposePasswordPrompt = function (shouldShow) {
        var pp = q$('composePasswordPrompt');
        if (!pp)
            return;
        var self = this;
        if (shouldShow) {
            Common.cshow(pp);
            DialogUtils.removeBodyScrollBars();
            var dialogElem_1 = q$('passwordDialogInnerDialog');
            var backgroundElem_1 = q$('passwordDialogBackground');
            self.boundDialogResizeFunc = function () {
                DialogUtils.handleDialogResize(dialogElem_1, backgroundElem_1);
            };
            self.boundDialogResizeFunc();
            window.addEvent('resize', self.boundDialogResizeFunc);
        }
        else {
            Common.chide(pp);
            DialogUtils.restoreBodyScrollBars();
            if (self.boundDialogResizeFunc != null) {
                window.removeEvent('resize', self.boundDialogResizeFunc);
                self.boundDialogResizeFunc = null;
            }
            this.enablePost();
        }
    };
    PeerMessageComposer.prototype.showPopupDialog = function (id, shouldShow) {
        var pd = q$(id);
        if (!pd)
            return;
        var self = this;
        if (shouldShow) {
            Common.cshow(pd);
            DialogUtils.removeBodyScrollBars();
            var dialogElem_2 = q$('dialogInnerDialog_' + id);
            var backgroundElem_2 = q$('dialogBackground_' + id);
            self.boundDialogResizeFunc = function () {
                DialogUtils.handleDialogResize(dialogElem_2, backgroundElem_2);
            };
            self.boundDialogResizeFunc();
            window.addEvent('resize', self.boundDialogResizeFunc);
        }
        else {
            Common.chide(pd);
            DialogUtils.restoreBodyScrollBars();
            if (self.boundDialogResizeFunc != null) {
                window.removeEvent('resize', self.boundDialogResizeFunc);
                self.boundDialogResizeFunc = null;
            }
        }
    };
    PeerMessageComposer.prototype.cancelComposePassword = function () {
        this.showComposePasswordPrompt(false);
    };
    PeerMessageComposer.prototype.confirmComposePassword = function () {
        var pwd = q$('composePassword').value;
        if (pwd == '')
            return;
        var xmlRefresh = XML.CreateDocument("<checkPassword></checkPassword>");
        var docElem = xmlRefresh.documentElement;
        docElem.setAttribute("pwd", pwd);
        var url = QSettings.postUrl() + ";ssl";
        var self = this;
        Ajax.postAsXml(url, xmlRefresh, function (resp) {
            var respDoc = XML.CreateDocument(resp);
            var act = respDoc.documentElement.getAttribute("act");
            if (act == null) {
                self.confirmPasswordFailure();
            }
            else {
                gQCredentials.createLastActivityCookies(act);
                self.confirmPasswordSuccess();
            }
        }, function () {
            self.confirmPasswordFailure();
        });
    };
    PeerMessageComposer.prototype.confirmPasswordSuccess = function () {
        Common.chide('composePassword_error');
        this.showComposePasswordPrompt(false);
        this.dfRequest.submit(this.onSubmitSuccess.bind(this), this.onSubmitFailure.bind(this));
    };
    PeerMessageComposer.prototype.confirmPasswordFailure = function () {
        var errElt = q$('composePassword_error');
        errElt.innerHTML = QSTR.loginPasswordIncorrectText;
        Common.cshow(errElt);
        q$('composePassword').focus();
    };
    PeerMessageComposer.prototype.updatePublishButton = function () {
        var pubElt = q$('publishLink');
        if (pubElt) {
            var validationError = this.validate();
            var disable = !!(validationError || this.submissionPending);
            pubElt.toggleClass('disabledButton', disable);
        }
    };
    PeerMessageComposer.prototype.populateDfRequest = function () {
        this.dfRequest.title = q$('emailSubject').get('value').trim();
        this.dfRequest.userData = q$('emailBody').value.trim();
        if (q$('peerMessageRecipients')) {
            var aryDiscussionMembers = this.getDiscussionMembers();
            this.dfRequest.SetDiscussionMembers(aryDiscussionMembers);
        }
        this.dfRequest.referralDfid = this.presetReferralDfid;
        this.dfRequest.referralURI = this.presetReferralURI;
        if (this.presetReferralDfTitle != "")
            this.dfRequest.referralDfTitle = this.presetReferralDfTitle;
    };
    PeerMessageComposer.prototype.onSubmitSuccess = function () {
        q$(document.body).removeClass("loading");
        window.onbeforeunload = null;
        this.DisplaySentDiv();
    };
    PeerMessageComposer.prototype.onSubmitFailure = function () {
        q$(document.body).removeClass("loading");
        this.enablePost();
    };
    PeerMessageComposer.prototype.publish = function () {
        if (q$('publishLink').hasClass('disabledButton'))
            return;
        if (this.submissionPending)
            return false;
        this.disablePost();
        var validationResult = this.validate();
        if (validationResult) {
            alert(validationResult);
            this.onSubmitFailure();
            return false;
        }
        this.populateDfRequest();
        if (this.dfRequest.requiresInactivityTimeout) {
            // for locked messages (those with requiresInactivityTimeout set),
            // do async check checks before allowing content to be submitted,
            this.checkInactivityBeforeSubmit();
            return false;
        }
        else {
            q$(document.body).addClass("loading");
            this.dfRequest.submit(this.onSubmitSuccess.bind(this), this.onSubmitFailure.bind(this));
        }
        return false;
    };
    PeerMessageComposer.prototype.DisplaySentDiv = function () {
        var aryMembers = this.getDiscussionMembers();
        if (typeof QModalDialog !== 'undefined')
            QModalDialog.requestNewTitle(QSTR.messageConfirmation);
        Common.chide('emailMessages');
        Common.cshow('emailConfirmation');
        var dlgTitleElt = q$('dialogTitle');
        var receiptDivElt = q$('receiptDiv');
        if (dlgTitleElt)
            dlgTitleElt.innerHTML = QSTR.confirmation;
        if (!receiptDivElt)
            return;
        var numRecips = aryMembers.length;
        var displayname, td1, i, tr;
        var j = 0;
        var numToAdd = 0;
        for (i = 0; i < numRecips; i++) {
            tr = document.createElement('div');
            td1 = document.createElement("div");
            td1.className = 'nameTd';
            displayname = this.findDisplayName(aryMembers[i]);
            td1.innerHTML = displayname;
            var td2 = document.createElement("div");
            td2.className = "statusTd";
            var irecip = aryMembers[i];
            if (this.inPersonalAB(irecip)) {
                td2.innerHTML = '<span id="' + irecip + '" class="inContacts">' + QSTR.inContacts + '</span>';
            }
            else {
                td2.innerHTML = '<a id="' + irecip + '" href="#" onclick="return PeerMessageComposer.INST.addToAddressBook(this.id);">' + QSTR.addToContacts + '</a>';
                numToAdd++;
                this.newEmailMessageAddresses[j] = irecip;
                j++;
            }
            // td2 goes in first, since it floats right
            tr.appendChild(td2);
            tr.appendChild(td1);
            receiptDivElt.appendChild(tr);
        }
        if (numToAdd > 1) {
            tr = document.createElement("div");
            tr.id = 'addAll';
            tr.style = 'padding-top:30px;';
            tr.innerHTML = '<div style="padding-top:30px; float: right;"><a href="#" onclick="return PeerMessageComposer.INST.addToAddressBook();">' + QSTR.addAllToContacts + '</a></div>';
            receiptDivElt.appendChild(tr);
        }
        // at this stage the dialog is already initialized and visible=> only needs UI update
        window.parent.PeerMsgComposerLauncher.peerMsgDlg.setHeight("520px");
        window.parent.PeerMsgComposerLauncher.peerMsgDlg.update();
    };
    PeerMessageComposer.prototype.updateContactStatus = function (contacts) {
        for (var i = 0; i < contacts.length; i++) {
            var id = contacts[i];
            var parent_1 = document.getElementById(id);
            parent_1.innerHTML = '<span id="' + id + '" class="inContacts">' + QSTR.inContacts + '';
        }
        var aa = q$('addAll');
        if (this.newEmailMessageAddresses.length == 0 && aa != null) {
            aa.style.display = "none";
        }
    };
    PeerMessageComposer.prototype.inPersonalAB = function (name) {
        var dm = this.currentAB;
        if (!dm)
            return false;
        for (var i = 0; i < dm.length; i++) {
            var inPAB = (dm[i].getAttribute("data-inpab") == "1");
            if (dm[i].value == name && inPAB) {
                return true;
            }
        }
        return false;
    };
    PeerMessageComposer.prototype.goToInbox = function () {
        this.dialogClose();
    };
    PeerMessageComposer.prototype.addToAddressBook = function (contact) {
        q$('addressBookCandidates').set('html', '');
        var toAdd = [];
        var i;
        if (contact) {
            toAdd[0] = contact;
            for (i = 0; i < this.newEmailMessageAddresses.length; i++) {
                if (this.newEmailMessageAddresses[i] == contact) {
                    this.newEmailMessageAddresses.splice(i, 1);
                    break;
                }
            }
        }
        else {
            toAdd = this.newEmailMessageAddresses;
            this.newEmailMessageAddresses = [];
        }
        var elem;
        var referUrl = QSettings.postUrl();
        var xmlDoc = XML.CreateDocument("<qmsg></qmsg>");
        var qMsgElem = xmlDoc.documentElement;
        qMsgElem.setAttribute("cmd", "postAddressBook");
        for (i = 0; i < toAdd.length; ++i) {
            elem = xmlDoc.createElement('address_entry');
            elem.setAttribute('email', toAdd[i]);
            elem.setAttribute('disabled', '0');
            qMsgElem.appendChild(elem);
        }
        //window.tempEmailMessage = this;
        var self = this;
        Ajax.postAsXml(referUrl, xmlDoc, function () {
            //console.log(toAdd);
            self.updateContactStatus(toAdd);
        }, function () {
            alert("Error adding contact(s)");
        });
        return false;
    };
    PeerMessageComposer.prototype.findDisplayName = function (emailorscreendoor) {
        var displayname = "";
        if (emailorscreendoor.indexOf("@") > -1) {
            displayname = emailorscreendoor;
        }
        else {
            for (var i = 0; i < this.currentAB.length; i++) {
                if (this.currentAB[i].value == emailorscreendoor) {
                    displayname = this.currentAB[i].text;
                    break;
                }
            }
            if ((displayname == "") && (this.prepopulatedEntry != ""))
                displayname = this.prepopulatedEntry.text;
        }
        return displayname;
    };
    PeerMessageComposer.handleResize = function () {
        var toField = q$('peerMessageRecipients');
        if (toField.chosen) {
            var w = q$('emailSubject').getSize().x;
            toField.chosen.resize_container_width(w);
        }
    };
    PeerMessageComposer.containsInvalidEmail = function () {
        var li = $$('li');
        if (!li)
            return false;
        for (var i = 0; i < li.length; i++) {
            if (li[i].hasClass("invalid-search-choice"))
                return true;
        }
        return false;
    };
    PeerMessageComposer.startDialogOnPageReady = function (args) {
        PeerMessageComposer.INST = new PeerMessageComposer(args);
    };
    PeerMessageComposer.makeForTablet = function () {
        PeerMessageComposer.INST = new PeerMessageComposer();
        PeerMessageComposer.INST.getAddressBookViaAjax();
    };
    // remnants of singleton
    PeerMessageComposer.INST = null;
    return PeerMessageComposer;
}());
function displayMobileConfirmboxBackground(confirmboxTop, confirmboxLeft, confirmbox, confirmbox_bckgrnd) {
    confirmbox_bckgrnd.setStyle('top', (-1) * confirmboxTop);
    confirmbox_bckgrnd.setStyle('left', (-1) * confirmboxLeft);
    confirmbox_bckgrnd.setStyle('height', confirmbox.parentNode.getSize().y);
    confirmbox_bckgrnd.setStyle('width', confirmbox.parentNode.getSize().x);
}

//include "Utf8.js"
//include "PeerMsgComposerLauncher.js"
//include "ScreenDoor.js"
//include "AddressBook.js"



// PeerMsgComposerLauncher.js

//xnclude "DialogUtils.js"
//xnclude "PeerMessageComposer.js"
/// <reference path="Common.d.ts" />
/// <reference path="Mootools.d.ts" />
/// <reference path="DialogUtils.ts" />
// Shows the popup dialog that will contain the composer within an IFrame.
// We MUST use an IFrame when the containing page has been delivered via
// HTTP, since the compose form must be HTTPS (PeerMsg's require encryption).
var PeerMsgComposerLauncher = (function () {
    // constructor should not be called externally. It is invoked through
    // static PeerMsgComposerLauncher.launch
    function PeerMsgComposerLauncher(to, refuri, refdfid, reftitle) {
        this.to = "";
        this.referralDfid = 0;
        this.referralURI = '';
        this.referralDfTitle = "";
        this.restartAfterRefer = false;
        this.to = "";
        this.referralDfid = 0;
        this.referralURI = '';
        this.referralDfTitle = "";
        if (to)
            this.to = to;
        if (refuri)
            this.referralURI = refuri;
        if (refdfid)
            this.referralDfid = refdfid;
        if (reftitle)
            this.referralDfTitle = reftitle;
    }
    PeerMsgComposerLauncher.getEffectiveContainerElt = function () {
        var contElt = q$(PeerMsgComposerLauncher.defContainerEltName);
        if (!contElt)
            contElt = q$(PeerMsgComposerLauncher.altContainerEltName);
        if (!contElt)
            contElt = q$(PeerMsgComposerLauncher.referOptionsContainerName);
        return contElt;
    };
    /**
     *
     * @param {QModalDialog} dlgElt
     * @param {boolean} hideTitle hide/show the dialog title (by default the title is shown)
     */
    PeerMsgComposerLauncher.prototype.show = function (dlgElt, hideTitle) {
        var src = QSettings.buildComposePeerMsgUrl(this.to, this.referralDfid, this.referralURI, this.referralDfTitle, this.isInsideInbox());
        this.pausePlayerForReferral();
        var myHeight = "500px";
        dlgElt = dlgElt || PeerMsgComposerLauncher.peerMsgDlg;
        dlgElt.setContent(src);
        dlgElt.setHeight(myHeight);
        dlgElt.showTitle(hideTitle !== true);
        var self = this;
        function resetOnHide() {
            self.resumePlayerAfterReferral();
            var container = PeerMsgComposerLauncher.getEffectiveContainerElt();
            Common.chide(container);
            if (this.refreshAddressBook) {
                this.refreshAddressBook();
            }
            return true;
        }
        dlgElt.show(resetOnHide);
    };
    /**
     *  Tells if the current page is Inbox
     * @returns {boolean}
     */
    PeerMsgComposerLauncher.prototype.isInsideInbox = function () {
        var isInInbox = (!!q$('isInInbox'));
        return isInInbox;
    };
    PeerMsgComposerLauncher.prototype.pausePlayerForReferral = function () {
        if (q$('playPause') == null)
            return;
        var df = Common.currentDfInPlayer();
        if (!df)
            return;
        var stateMgr = Common.currentDfInPlayer().getStateManager();
        if (!stateMgr)
            return;
        if (stateMgr.isAudioPlaying()) {
            this.restartAfterRefer = true;
            stateMgr.setAudioPlaying(false);
        }
    };
    PeerMsgComposerLauncher.prototype.resumePlayerAfterReferral = function () {
        var df = Common.currentDfInPlayer();
        if (!df)
            return;
        var stateMgr = df.getStateManager();
        if (!stateMgr)
            return;
        if (this.restartAfterRefer) {
            stateMgr.setAudioPlaying(true);
            this.restartAfterRefer = false;
        }
        stateMgr.ResumePresentation();
    };
    PeerMsgComposerLauncher.launchForWeb = function (toScreenDoor, toDislayName, refuri, refdfid, reftitle) {
        // prepare the dialog that contains the iFrame. Do this only once.
        if (!PeerMsgComposerLauncher.peerMsgDlg) {
            var dlgElt = this.getEffectiveContainerElt();
            PeerMsgComposerLauncher.peerMsgDlg = new QModalDialog(dlgElt, QSTR.composeMessage, true);
        }
        var inst = new PeerMsgComposerLauncher(toScreenDoor, refuri, refdfid, reftitle);
        inst.show();
        return false;
    };
    PeerMsgComposerLauncher.launchForTablet = function (toScreenDoior, toDsiplayName, refuri, refdfid, reftitle) {
        // bug 2056 - callback is added to avoid closing compose dialog on tablet if background is clicked.
        // tablets lightbox-style dialog
        QModalLite.showModal((q$('emailMessageInnerContainer')), Common.returnFalse);
        PeerMessageComposer.makeForTablet();
        //TODO: PeerMessageInbox.addResizeHandler(PeerMessageInbox.handleDialogResize);
    };
    PeerMsgComposerLauncher.launchForHandset = function (toScreenDoor, toDisplayName) {
        var msg = {};
        if (toScreenDoor) {
            msg.screendoor = toDisplayName;
            msg.name = toDisplayName;
        }
        HomeBrowser.sendPanelMessage("home", "composePrivate", JSON.encode(msg), true);
    };
    PeerMsgComposerLauncher.launch = function (toScreenDoor, toDisplayName, refuri, refdfid, reftitle) {
        if (PageFlavor.isFromApp()) {
            if (PeerMessageInbox.showInInbox()) {
                // tablets use lightbox-style dialog; for BOTH app and mor
                PeerMsgComposerLauncher.launchForTablet(toScreenDoor, refuri, refdfid, reftitle);
            }
            else {
                // single-column (phone) devices go to compose page
                PeerMsgComposerLauncher.launchForHandset(toScreenDoor, toDisplayName);
            }
        }
        else if (PageFlavor.isMoBr()) {
            PeerMsgComposerLauncher.launchForTablet(toScreenDoor, refuri, refdfid, reftitle);
        }
        else {
            PeerMsgComposerLauncher.launchForWeb(toScreenDoor, refuri, refdfid, reftitle);
        }
        return false;
    };
    PeerMsgComposerLauncher.launchFromQSCL = function (toScreenDoor, toName) {
        // only called from player pages
        if (Common.isWeb()) {
            PeerMsgComposerLauncher.launchForWeb(toScreenDoor, toName, null);
        }
        else {
            PlayerWrapper.sendPanelMessage(PanelName.player, "pause", {});
            PlayerWrapper.sendPanelMessage(PanelName.player, "bringToFront", { "id": PanelName.compose });
            PlayerWrapper.sendPanelMessage(PanelName.compose, PanelName.compose, "updateRecipient", {
                "type": "compose",
                "authorScreenDoor": toScreenDoor,
                "authorName": toName
            });
        }
    };
    // static QModalDialog instance.  Initialized only once per life of page
    PeerMsgComposerLauncher.peerMsgDlg = null;
    PeerMsgComposerLauncher.defContainerEltName = 'emailMessageContainer';
    PeerMsgComposerLauncher.altContainerEltName = 'peerMessageContainer';
    PeerMsgComposerLauncher.referOptionsContainerName = 'referOptionsContainer';
    return PeerMsgComposerLauncher;
}());

//include "DialogUtils.js"
//include "PeerMessageComposer.js"



// Comment.js

/**
 * Copyright 2015 Quantia Inc
 * Created by david.barbrow on 5/1/2015.
 */
//xnclude "StringBuilder.js"
//xnclude "DateUtils.js"
//xnclude "PeerMsgComposerLauncher.js"
/// <reference path="AccountInfoBase.ts" />
/// <reference path="Ajax.d.ts" />
/// <reference path="mootools.d.ts" />
/// <reference path="Common.d.ts" />
/// <reference path="IQSettings.d.ts" />
/// <reference path="QUtils.ts" />
/// <reference path="PeerMsgComposerLauncher.ts" />
/// <reference path="feature/DelayedBackground.ts" />
/// <reference path="PopupPreview.ts" />
// Note: Comment is already defined in Typescript's lib.d.ts as something else...
// so define our Comment object as a QComment
//
var QComment = (function () {
    function QComment() {
        this.canComment = false;
        this.canUpvote = false;
        this.cmntTimeMs = 0;
        this.commentDepth = 0;
        this.commentId = -1;
        this.commentStatus = null;
        this.commentText = "";
        this.hasAuthorReply = false;
        this.hasSentThumbsUp = false;
        this.isAuthorComment = false;
        this.isContactOptOut = true;
        this.isCurrentUserAnAuthor = false;
        this.isFlaggedForAuthorReply = false;
        this.isForWeb = false;
        this.isHighlightComment = false;
        this.isFromMobile = false;
        this.isNew = false;
        this.isUserObserver = false;
        this.parentComment = null;
        this.position = 0;
        this.showContact = true;
        this.userDisplayName = null;
        this.userInstitution = "";
        this.userPhotoVersion = null;
        this.userQid = null;
        this.userTitle = "";
        this.votes = 0;
        /**
         * The server will compute a "featured" order and will
         * assign a "featuredPosition" to every comment... use this
         * when sorting by "featured"
         */
        this.featuredPosition = 0;
        this.weightOfNextUpvote = 0;
        this.attachments = [];
        this.urls = [];
        this.children = [];
    }
    QComment.FromXML = function (xmlElem, depth, isCurrentUserAnAuthor) {
        var result = null;
        try {
            result = new QComment();
            result.ParseXml(xmlElem, depth, isCurrentUserAnAuthor);
        }
        catch (e) {
            Common.addDebugStr("EXC QComment.FromXML " + e);
        }
        return result;
    };
    QComment.FromUser = function (commentText, attachments) {
        var c = new QComment();
        c.commentText = commentText;
        c.userQid = gQCredentials.UserCode;
        c.userDisplayName = AccountInfo.DisplayName;
        c.userPhotoVersion = gQCredentials.PhotoVersion;
        c.userTitle = AccountInfo.Title;
        c.showContact = false;
        c.cmntTimeMs = new Date().getTime();
        c.attachments = attachments;
        // set featuredPosition to BIG number, but one that
        // can be less than the NEXT comment a user might make.
        c.featuredPosition = c.cmntTimeMs;
        return c;
    };
    QComment.setUriDfidAndTitle = function (uri, dfid, title) {
        QComment.refURI = uri;
        QComment.refDfid = dfid;
        QComment.refTitle = title;
    };
    QComment.contactMemberFromComment = function (quid) {
        return PeerMsgComposerLauncher.launch(quid, null, QComment.refURI, QComment.refDfid, QComment.refTitle);
    };
    QComment.prototype.GetCommentId = function () {
        return this.commentId;
    };
    QComment.prototype.getCommentDepth = function () {
        return this.commentDepth;
    };
    QComment.prototype.GetChildren = function () {
        return this.children;
    };
    QComment.prototype.getCommentTimeMs = function () {
        return this.cmntTimeMs;
    };
    QComment.prototype.getParentID = function () {
        if (this.parentComment == null)
            return 0;
        return Number(this.parentComment.commentId);
    };
    QComment.prototype.getVotes = function () {
        return this.votes;
    };
    QComment.prototype.getFeaturedPosition = function () {
        return this.featuredPosition;
    };
    QComment.prototype.bringIntoView = function () {
        var elt = q$('comment' + this.commentId);
        elt.scrollIntoView();
    };
    QComment.prototype.hasComeIntoView = function () {
        var commentElem = q$('comment' + this.commentId);
        if (!commentElem.hasAttribute('data-isInView')) {
            commentElem.setAttribute('data-isInView', 'true');
            DelayedBackground.loadImages(commentElem);
            PopupPreview.Update(commentElem);
            HoverStates.addHoverFunctions(commentElem);
        }
    };
    QComment.prototype.isGoodComment = function () {
        return this.commentStatus !== "normal";
    };
    QComment.prototype.IsHighlightComment = function () {
        return this.isHighlightComment;
    };
    QComment.prototype.MarkAsHighlightComment = function () {
        this.isHighlightComment = true;
        if (this.parentComment) {
            this.parentComment.MarkAsHighlightComment();
        }
    };
    QComment.prototype.IsAuthorComment = function () {
        return this.isAuthorComment;
    };
    QComment.prototype.MarkAsAuthorCommentOrReply = function () {
        this.isAuthorComment = true;
        if (this.parentComment) {
            this.parentComment.MarkAsAuthorCommentOrReply();
        }
    };
    QComment.prototype.MarkAsCanComment = function () {
        this.canComment = true;
    };
    QComment.prototype.MarkAsCanUpvote = function () {
        this.canUpvote = true;
    };
    QComment.prototype.MarkAsNew = function () {
        if (this.userQid !== gQCredentials.UserCode) {
            this.isNew = true;
        }
    };
    QComment.prototype.UnMarkAsNew = function () {
        this.isNew = false;
    };
    QComment.prototype.getUpvoteWeight = function () {
        return this.weightOfNextUpvote;
    };
    QComment.prototype.setUpvoteWeight = function (upvoteWeight) {
        this.weightOfNextUpvote = upvoteWeight;
    };
    QComment.prototype.getSortTimestamp = function () {
        var result = this.cmntTimeMs;
        if (this.children.length > 0) {
            for (var i = 0; i < this.children.length; i++) {
                result = Math.max(result, this.children[i].getSortTimestamp());
            }
        }
        return result;
    };
    QComment.prototype.AddChildComment = function (newComment) {
        newComment.parentComment = this;
        this.children.push(newComment);
    };
    QComment.prototype.parseAttachments = function (xmlElem) {
        var attachmentsElem = XML.getElementByTagNameOneLevel(xmlElem, "attachments");
        if (!attachmentsElem)
            return;
        var attachmentElems = XML.getElementsByTagNameOneLevel(attachmentsElem, "attachment");
        if (!attachmentElems)
            return;
        for (var i = 0; i < attachmentElems.length; ++i) {
            var aa = attachmentElems[i];
            var o = {
                key: "/q-qcp/" + aa.getAttribute("key"),
                filename: aa.getAttribute("filename"),
                type: "file"
            };
            this.attachments.push(o);
        }
    };
    QComment.prototype.parseAttachedUrls = function (xmlElem) {
        var urlsElem = XML.getElementByTagNameOneLevel(xmlElem, "urls");
        if (!urlsElem)
            return;
        var urlElems = XML.getElementsByTagNameOneLevel(urlsElem, "url");
        if (!urlElems)
            return;
        for (var i = 0; i < urlElems.length; ++i) {
            var o = {
                key: XML.findAndFillValue(urlElems[i]),
                filename: XML.findAndFillValue(urlElems[i]),
                type: "url"
            };
            this.attachments.push(o);
        }
    };
    QComment.prototype.parseChildren = function (xmlElem, isCurrentUserAnAuthor) {
        var childComments = XML.getElementByTagNameOneLevel(xmlElem, "child_comments");
        if (!childComments)
            return;
        var children = XML.getElementsByTagNameOneLevel(childComments, "comment");
        // replyCount = children.length;
        for (var i = 0; i < children.length; ++i) {
            var child = QComment.FromXML(children[i], this.commentDepth + 1, isCurrentUserAnAuthor);
            child.parentComment = this;
            this.children.push(child);
        }
    };
    QComment.prototype.parseDeviceClass = function (xmlElem) {
        var devclass = xmlElem.getAttribute("deviceClass");
        if (devclass !== "web" &&
            devclass !== "" &&
            devclass !== null) {
            this.isFromMobile = true;
        }
    };
    QComment.prototype.ParseXml = function (xmlElem, depth, isCurrentUserAnAuthor) {
        //confirm("id= " + xmlElem.getAttribute("id"));
        var child, children, dt, i, o, serverTime, urlElems;
        this.commentDepth = depth;
        this.isCurrentUserAnAuthor = isCurrentUserAnAuthor;
        this.commentId = Number(xmlElem.getAttribute("id"));
        this.isAuthorComment = ("true" == xmlElem.getAttribute("isAuthor"));
        this.isFlaggedForAuthorReply = (xmlElem.getAttribute("forReply") === 'true');
        this.hasAuthorReply = (xmlElem.getAttribute("hasAuthorReply") === 'true');
        this.commentStatus = XML.findAndFillValueOneLevel(xmlElem, "status");
        this.featuredPosition = XML.findAndFillValueOneLevel(xmlElem, "featuredPosition");
        this.commentText = unescape(XML.findAndFillValueOneLevel(xmlElem, "text"));
        // parse the date of the comment
        dt = XML.getElementsByTagName(xmlElem, "date");
        if (dt) {
            serverTime = DateUtils.fromServerTime3(dt[0].childNodes[0].nodeValue);
            this.cmntTimeMs = DateUtils.convertToClientTimeMs(serverTime);
        }
        // parse children comments
        this.parseChildren(xmlElem, isCurrentUserAnAuthor);
        var childComments = XML.getElementByTagNameOneLevel(xmlElem, "child_comments");
        // check if we should show a mobile icon
        this.parseDeviceClass(xmlElem);
        // basic display details about commentor
        this.userQid = XML.findAndFillValueOneLevel(xmlElem, "user_name");
        this.userDisplayName = XML.findAndFillValueOneLevel(xmlElem, "display_name");
        this.userInstitution = XML.findAndFillValueOneLevel(xmlElem, "institution");
        this.userTitle = XML.findAndFillValueOneLevel(xmlElem, "user_title");
        // can we show a photo?
        var pv = xmlElem.getAttribute("photo_version");
        this.userPhotoVersion = (pv) ? Number(pv) : 0;
        if (this.userPhotoVersion <= 0) {
            this.userPhotoVersion = null;
        }
        // allow a "+ Contact" option?
        this.showContact = (XML.findAndFillValueOneLevel(xmlElem, "isUserContactOptOut") !== "true");
        this.isContactOptOut = !this.showContact;
        if (this.userQid === gQCredentials.UserCode) {
            this.showContact = false;
        }
        this.isUserObserver = (XML.findAndFillValueOneLevel(xmlElem, "isUserObserver") == "true");
        // upvotes?
        var voteElement = XML.getElementByTagNameOneLevel(xmlElem, "votes");
        if (voteElement !== null) {
            this.votes = parseInt(voteElement.getAttribute("upvotes"), 10);
        }
        //confirm("parse attachments" + xmlElem.getAttribute("id"));
        this.parseAttachments(xmlElem);
        this.parseAttachedUrls(xmlElem);
    };
    QComment.prototype.getReplyDiv = function (jst) {
        var strHtml = jst.process({ commentId: this.commentId }, { throwExceptions: true });
        return strHtml + "";
    };
    QComment.prototype.toHTML = function (jst) {
        var childrenHTML = "", i;
        var childComment;
        if (this.children.length > 0) {
            var strings = [];
            for (i = 0; i < this.children.length; i++) {
                childComment = this.children[i];
                strings.push(childComment.toHTML(jst));
            }
            childrenHTML = strings.join('\n');
        }
        var df = Common.currentDfInPlayer();
        var supportsDiscussion = (df && df.nsSupportsFlagForAuthor());
        var canFlagForReply = (supportsDiscussion && !(this.hasAuthorReply || this.isAuthorComment));
        var isFromContextUser = (this.userQid == gQCredentials.UserCode);
        var newCssClass = this.userDisplayName !== '' ? 'new' : 'newWithoutAuthorName';
        var strHtml = jst.process({
            commentDepth: this.commentDepth,
            userQid: this.userQid,
            userPhotoVersion: this.userPhotoVersion,
            userDisplayName: this.userDisplayName,
            userDisplayNameEscaped: this.userDisplayName.replace(/'/g, "\\u0027"),
            userInstitution: this.userInstitution,
            userTitle: this.userTitle,
            showContactLink: this.showContact,
            isAuthorReply: this.isAuthorComment && (this.commentDepth > 0),
            isContactOptOut: this.isContactOptOut,
            isUserObserver: this.isUserObserver,
            isCommentFromContextUser: isFromContextUser,
            isForWeb: this.isForWeb,
            dateString: DateUtils.toCommentStyleDateTime(new Date(this.cmntTimeMs)),
            dateStringShort: DateUtils.toNumberedDateAndTime(new Date(this.cmntTimeMs)),
            commentText: this.commentText,
            isFromMobile: this.isFromMobile,
            commentId: this.commentId,
            votes: this.votes,
            childrenHTML: childrenHTML,
            status: this.commentStatus,
            attachments: this.attachments,
            isNewComment: this.isNew,
            canComment: this.canComment,
            canUpvote: this.canUpvote,
            isFlaggedForAuthorReply: this.isFlaggedForAuthorReply,
            isCurrentUserAnAuthor: this.isCurrentUserAnAuthor,
            canFlagForAuthorReply: canFlagForReply,
            isHighlightComment: this.isHighlightComment,
            newCssClass: newCssClass
        }, { throwExceptions: true });
        return strHtml + "";
    };
    QComment.prototype.updatePromotionDisplay = function (isPromoted) {
        this.commentStatus = (isPromoted) ? "promoted" : "normal";
        var promoteElt = q$('c_promote_' + this.commentId);
        if (promoteElt) {
            var unPromoteElt = q$('c_unpromote_' + this.commentId);
            promoteElt.toggleClass('exiledHidden', isPromoted);
            unPromoteElt.toggleClass('exiledHidden', !isPromoted);
        }
    };
    QComment.prototype.MarkAsPromoted = function () {
        var url = "/q-webclient?cmd=setcommentfeatured&featured=true&commentId=" + this.commentId;
        var self = this;
        Ajax.getText(url, function (e) {
            self.updatePromotionDisplay(true);
        });
    };
    QComment.prototype.UnMarkAsPromoted = function () {
        var url = "/q-webclient?cmd=setcommentfeatured&featured=false&commentId=" + this.commentId;
        var self = this;
        Ajax.getText(url, function (e) {
            self.updatePromotionDisplay(false);
        });
    };
    QComment.prototype.updateFlaggedForAuthoDisplay = function (isFlagged) {
        this.isFlaggedForAuthorReply = isFlagged;
        var markedELt = q$('c_mark_' + this.commentId);
        if (markedELt) {
            var unmarkedElt = q$('c_unmark_' + this.commentId);
            markedELt.toggleClass('exiledHidden', isFlagged);
            unmarkedElt.toggleClass('exiledHidden', !isFlagged);
        }
    };
    QComment.prototype.MarkForReply = function () {
        var url = "/q-webclient?cmd=flagForAuthorReply&forReply=true&commentId=" + this.commentId;
        var self = this;
        Ajax.getText(url, function (e) {
            self.updateFlaggedForAuthoDisplay(true);
        });
    };
    QComment.prototype.UnMarkForReply = function () {
        var url = "/q-webclient?cmd=flagForAuthorReply&forReply=false&commentId=" + this.commentId;
        var self = this;
        Ajax.getText(url, function (e) {
            self.updateFlaggedForAuthoDisplay(false);
        });
    };
    QComment.prototype.buildThumbsUpDoc = function (dfgid) {
        var xmlDoc = XML.CreateDocument("<qmsg></qmsg>");
        var qMsgElem = xmlDoc.documentElement;
        qMsgElem.setAttribute("cmd", "vote");
        qMsgElem.setAttribute("device", "web");
        var voteElem = xmlDoc.createElement("vote");
        qMsgElem.appendChild(voteElem);
        voteElem.setAttribute("commentId", this.commentId);
        voteElem.setAttribute("dfgid", dfgid);
        voteElem.setAttribute("type", 'upvote');
        voteElem.setAttribute("upvoteWeight", "" + this.weightOfNextUpvote);
        voteElem.setAttribute("position", "" + this.position);
        var df = Common.currentDfInPlayer();
        if (df) {
            voteElem.setAttribute("opendts", DateUtils.dateToString(df.getServerDfOpenTime()));
        }
        else if (Common.serverDfOpenTimeMs) {
            // in mobile comments panel
            var o = DateUtils.dateToString(new Date(Common.serverDfOpenTimeMs));
            voteElem.setAttribute("opendts", o);
        }
        return xmlDoc;
    };
    QComment.prototype.ThumbsUp = function (dfgid, onSuccess) {
        if (this.hasSentThumbsUp) {
            if (onSuccess !== undefined) {
                onSuccess(this.commentId, this.votes);
            }
            return;
        }
        this.hasSentThumbsUp = true;
        var url = QSettings.postUrl();
        var xmlDoc = this.buildThumbsUpDoc(dfgid);
        if (Common.isWeb()) {
            var self_1 = this;
            var processUpvoteDoc = function (str) {
                if (!str)
                    return;
                try {
                    var xmlDoc_1 = XML.CreateDocument(str);
                    var upVotes = XML.getAttributeFromTag(xmlDoc_1, "votes", "upvotes", "");
                    var commentId = XML.getAttributeFromTag(xmlDoc_1, "votes", "comment_id", "");
                    if (commentId !== "" && upVotes !== "") {
                        self_1.votes = parseInt(upVotes, 10);
                        if (onSuccess !== undefined) {
                            onSuccess(self_1.commentId, this.votes);
                        }
                    }
                    return;
                }
                catch (e) {
                }
            };
            Ajax.postAsXml(url, xmlDoc, processUpvoteDoc.bind(this), Common.doNothing);
        }
        else {
            Ajax.queueXmlToServer(url, xmlDoc);
            // on mobile, we won't get a document back so fake a thumb up (once)
            this.votes++;
            if (onSuccess) {
                onSuccess(this.commentId, this.votes);
            }
        }
    };
    QComment.refURI = '';
    QComment.refDfid = 0;
    QComment.refTitle = '';
    return QComment;
}());

//include "StringBuilder.js"
//include "DateUtils.js"
//include "PeerMsgComposerLauncher.js"



// Comments.js

/**
 * Copyright 2015 Quantia Inc
 * Created by david.barbrow on 5/1/2015.
 */
/// <reference path="Ajax.d.ts" />
/// <reference path="Comment.ts" />
/// <reference path="mootools.d.ts" />
/// <reference path="Common.d.ts" />
/// <reference path="IQSettings.d.ts" />
var Comments = (function () {
    /**
     * The server gives each comment a featuredPosition.  For the default sort policy, this is one of 10 buckets, so
     * many comments will actually collide on featuredPosition alone...  client disambiguates by sorting secondarily
     * on comment timestamp.
    statusWeight = {
        'highlighted': 10,
        'flaggedForAuthorReply': 9,
        'promotedAuthorComment': 8,
        'authorComment': 7,
        'promotedRepliedByAuthor': 6,
        'repliedByAuthor': 5,
        'promoted': 4,
        'featured': 3,
        'normal': 2
    };
    */
    function Comments(dataformGroup, dataformId) {
        this.dataformGroup = dataformGroup;
        this.dataformId = dataformId;
        this._qcmtsAry = [];
        this.currentUserIsAuthor = false;
        this.isSubmittingReply = false;
        this.totalCommentCount = 0;
        this.lastCommentTime = 0;
    }
    Comments.prototype.RefreshComments = function (highlightCommentId, onReady) {
        var self = this;
        var xmlIsland = null;
        this.displayConfirmMessage("Comments.RefreshComments ");
        xmlIsland = Common.getXmlDataIslandWithName('commentXml');
        if (xmlIsland) {
            if (this.ParseXml(xmlIsland)) {
                if (onReady)
                    onReady();
            }
        }
        else {
            var url = QSettings.buildGetCommentsXmlUrl(this.dataformId, "" + highlightCommentId);
            this.displayConfirmMessage("Comments.RefreshComments url " + url);
            Ajax.getXml(url, function (e) {
                if (this.ParseXml(e)) {
                    if (onReady)
                        onReady();
                }
            }.bind(this));
        }
    };
    Comments.prototype.MarkAsCanComment = function () {
        for (var i = 0; i < this._qcmtsAry.length; i++) {
            this._qcmtsAry[i].MarkAsCanComment();
        }
    };
    Comments.prototype.MarkAsCanUpvote = function () {
        for (var i = 0; i < this._qcmtsAry.length; i++) {
            this._qcmtsAry[i].MarkAsCanUpvote();
        }
    };
    Comments.prototype.ParseXml = function (xmlDoc) {
        var isOK = true;
        try {
            this._qcmtsAry = [];
            var commentsElems = XML.getElementByTagNameOneLevel(xmlDoc, "comments");
            if (!commentsElems)
                return isOK;
            if (commentsElems.getAttribute("total")) {
                this.totalCommentCount = parseInt(commentsElems.getAttribute("total"));
            }
            if (commentsElems.getAttribute("lastCommentTime")) {
                this.lastCommentTime = DateUtils.msFromServerTime3(commentsElems.getAttribute("lastCommentTime"));
            }
            if ("true" === commentsElems.getAttribute("currentUserIsAuthor")) {
                this.currentUserIsAuthor = true;
            }
            var commentElems = XML.getElementsByTagNameOneLevel(commentsElems, "comment");
            if (commentElems) {
                for (var i = 0; i < commentElems.length; i++) {
                    //this.displayConfirmMessage("QComment.FromXML: for i= " + i);
                    var cc = commentElems[i];
                    var comment = QComment.FromXML(cc, 0, this.IsCurrentUserAnAuthor());
                    this._qcmtsAry.push(comment);
                }
            }
            return isOK;
        }
        catch (e) {
            Common.addDebugStr("EXC Comments.ParseXML " + e);
            isOK = false;
        }
        return isOK;
    };
    Comments.prototype.displayConfirmMessage = function (msg) {
        // Common.addDebugStr(msg);
    };
    Comments._sortByFeaturedComparator = function (a, b) {
        var signum = b.getFeaturedPosition() - a.getFeaturedPosition();
        if (signum == 0)
            signum = b.getSortTimestamp() - a.getSortTimestamp();
        return signum;
    };
    Comments.prototype.IsCurrentUserAnAuthor = function () {
        return this.currentUserIsAuthor;
    };
    Comments.prototype.GetCommentsSortedByFeatured = function () {
        this._qcmtsAry.sort(Comments._sortByFeaturedComparator);
        this.setUpvoteWeights();
        return this._qcmtsAry;
    };
    Comments.prototype.GetCommentsSortedByTime = function () {
        this._qcmtsAry.sort(function (a, b) {
            return b.getSortTimestamp() - a.getSortTimestamp();
        });
        this.clearUpvoteWeights();
        return this._qcmtsAry;
    };
    Comments.prototype.GetCommentsSortedByReplies = function () {
        this._qcmtsAry.sort(function (a, b) {
            if (b.GetChildren().length === a.GetChildren().length) {
                return Comments._sortByFeaturedComparator(a, b);
            }
            return b.GetChildren().length - a.GetChildren().length;
        });
        this.clearUpvoteWeights();
        return this._qcmtsAry;
    };
    Comments.prototype.GetCommentsSortedByVotes = function () {
        this._qcmtsAry.sort(function (a, b) {
            if (b.getVotes() === a.getVotes()) {
                return b.getCommentTimeMs() - a.getCommentTimeMs();
            }
            return b.getVotes() - a.getVotes();
        });
        this.clearUpvoteWeights();
        return this._qcmtsAry;
    };
    Comments.prototype.canSortByVotes = function () {
        for (var i = 0; i < this._qcmtsAry.length; i++) {
            if (this._qcmtsAry[i].getVotes() > 0) {
                return true;
            }
        }
        return false;
    };
    Comments.prototype.canSortByReplies = function () {
        for (var i = 0; i < this._qcmtsAry.length; i++) {
            var c = this._qcmtsAry[i];
            if (c.GetChildren().length > 0) {
                return true;
            }
        }
        return false;
    };
    // TODO: djb... return to this
    Comments.prototype.canSortByFeatured = function () {
        return true;
    };
    Comments.prototype.setUpvoteWeights = function () {
        var index = 0;
        var thresholds = [0, 1, 2, 5, 10, -1];
        var weights = [1, 2, 3, 5, 10, -1];
        var weight;
        for (var i = 0; i < this._qcmtsAry.length; ++i) {
            var comment = this._qcmtsAry[i];
            if (comment.getParentID() != 0)
                continue;
            if (index == thresholds[0]) {
                thresholds.splice(0, 1);
                weight = weights[0];
                weights.splice(0, 1);
            }
            comment.weightOfNextUpvote = weight;
            ++index;
        }
    };
    Comments.prototype.clearUpvoteWeights = function () {
        var len = this._qcmtsAry.length;
        for (var i = 0; i < len; ++i) {
            this._qcmtsAry[i].weightOfNextUpvote = 0;
        }
    };
    Comments.prototype.findLatestCommentTimeMs = function () {
        var allComments = this.GetFlattenedCommentList();
        var latest = null;
        for (var i = 0; i < allComments.length; i++) {
            var c = allComments[i];
            if (!latest || c.getCommentTimeMs() > latest.getCommentTimeMs()) {
                latest = c;
            }
        }
        if (latest) {
            return Math.max(latest.getCommentTimeMs(), this.lastCommentTime);
        }
        return this.lastCommentTime;
    };
    Comments.prototype.getAuthorReplyCount = function () {
        var allComments = this.GetFlattenedCommentList();
        var count = 0;
        for (var i = 0; i < allComments.length; i++) {
            var c = allComments[i];
            if (c.parentComment != null && c.isAuthorComment) {
                count += 1;
            }
        }
        return count;
    };
    Comments.prototype.GetFlattenedCommentList = function (list) {
        if (list === undefined) {
            return this.GetFlattenedCommentList(this._qcmtsAry);
        }
        var result = list;
        for (var i = 0; i < list.length; i++) {
            if (list[i].GetChildren().length > 0) {
                result = result.concat(this.GetFlattenedCommentList(list[i].GetChildren()));
            }
        }
        return result;
    };
    Comments.prototype.getCommentCount = function () {
        var allComments = this.GetFlattenedCommentList();
        return Math.max(allComments.length, this.totalCommentCount);
    };
    // we may be told that there are more comments than we were given... but how
    // many were we given?
    Comments.prototype.GetDisplayableCommentCount = function () {
        var allComments = this.GetFlattenedCommentList();
        return allComments.length;
    };
    Comments.prototype.MarkAuthorCommentsOrReplies = function () {
        var allComments = this.GetFlattenedCommentList();
        for (var i = 0; i < allComments.length; i++) {
            if (allComments[i].IsAuthorComment()) {
                allComments[i].MarkAsAuthorCommentOrReply();
            }
        }
    };
    Comments.prototype.markNewComments = function (ifNewerThanTimestamp, onlyMarkGoodComments) {
        var count = 0;
        var allComments = this.GetFlattenedCommentList();
        for (var i = 0; i < allComments.length; i++) {
            var c = allComments[i];
            if (onlyMarkGoodComments) {
                if (c.isGoodComment() && c.getCommentTimeMs() > ifNewerThanTimestamp) {
                    c.MarkAsNew();
                    count++;
                }
            }
            else {
                if (c.getCommentTimeMs() > ifNewerThanTimestamp) {
                    c.MarkAsNew();
                    count++;
                }
            }
        }
        return count;
    };
    Comments.prototype.unMarkNewComments = function () {
        var count = 0;
        var allComments = this.GetFlattenedCommentList();
        for (var i = 0; i < allComments.length; i++) {
            allComments[i].UnMarkAsNew();
        }
        return count;
    };
    Comments.prototype.Follow = function () {
        var url = "/q-webclient/?cmd=setfollowing&dfg=" + this.dataformGroup + "&following=" + true + "&cb=" + DateUtils.msNow();
        Ajax.getText(url, Common.doNothing);
    };
    Comments.prototype.UnFollow = function () {
        var url = "/q-webclient/?cmd=setfollowing&dfg=" + this.dataformGroup + "&following=" + false + "&cb=" + DateUtils.msNow();
        Ajax.getText(url, Common.doNothing);
    };
    Comments.validateComment = function (commentText, attachmentHandler) {
        if (attachmentHandler && attachmentHandler.areUploadsPending()) {
            alert(QSTR.commentUploadsPending);
            return false;
        }
        commentText = commentText.trim();
        if (containsNonBasicMultilingualCharacter(commentText)) {
            alert(QSTR.invalidCommentCharacter);
            return false;
        }
        if (commentText.length === 0) {
            alert(QSTR.commentIsEmpty);
            return false;
        }
        return true;
    };
    Comments.prototype.addComment = function (comment) {
        this._qcmtsAry.push(comment);
    };
    Comments.prototype.findComment = function (commentId, list) {
        var childResult;
        var tmpID;
        if (list === undefined) {
            return this.findComment(commentId, this._qcmtsAry);
        }
        for (var i = 0; i < list.length; i++) {
            var cmnt = list[i];
            tmpID = cmnt.GetCommentId();
            if (Number(tmpID) === commentId) {
                return cmnt;
            }
            var children = cmnt.GetChildren();
            if (children && children.length > 0) {
                childResult = this.findComment(commentId, children);
                if (childResult) {
                    return childResult;
                }
            }
        }
        return null;
    };
    Comments.prototype.Submit = function (parentComment, commentText, attachmentHandler, onSuccess) {
        if (this.isSubmittingReply)
            return;
        this.isSubmittingReply = true;
        var url = QSettings.postUrl();
        commentText = Common.encodeToHTMLRespectingNewLinesAndSpaces(commentText.trim());
        var xmlDoc = XML.CreateDocument("<qmsg></qmsg>");
        var qMsgElem = xmlDoc.documentElement;
        qMsgElem.setAttribute("cmd", "postComment");
        qMsgElem.setAttribute("device", "web");
        var commentElem = xmlDoc.createElement("comment");
        qMsgElem.appendChild(commentElem);
        var df = Common.currentDfInPlayer();
        var c = null;
        var o = null;
        if (df) {
            c = DateUtils.dateToString(df.calcCurrentServerTime());
            o = DateUtils.dateToString(df.getServerDfOpenTime());
        }
        else if (Common.serverDfOpenTimeMs !== 0) {
            // in mobile comments panel
            c = DateUtils.dateToString(new Date(Common.calcCurrentServerTimeMs()));
            o = DateUtils.dateToString(new Date(Common.serverDfOpenTimeMs));
        }
        commentElem.setAttribute("clientdts", c);
        commentElem.setAttribute("opendts", o);
        commentElem.setAttribute("df", this.dataformId);
        commentElem.setAttribute("dfg", this.dataformGroup);
        if (parentComment) {
            commentElem.setAttribute("parentcomment", parentComment.GetCommentId());
        }
        commentElem.appendChild(XML.CreateTextNode(xmlDoc, commentText));
        if (attachmentHandler && (typeof attachmentHandler !== 'undefined')) {
            var attachmentsElem = xmlDoc.createElement("attachments");
            attachmentHandler.toXml(xmlDoc, attachmentsElem);
            commentElem.appendChild(attachmentsElem);
        }
        var postProcess = function (resp) {
            this.isSubmittingReply = false;
            var attachments = [];
            if (attachmentHandler && (typeof attachmentHandler !== 'undefined')) {
                attachments = attachmentHandler.toJSON();
            }
            var newComment = QComment.FromUser(commentText, attachments);
            var isNowFollowing = false;
            // on mobile, we won't have a response, so skip this
            if (resp) {
                try {
                    var doc = XML.CreateDocument(resp);
                    if (XML.findAndFillValue(doc, "isFollowing") === "true") {
                        isNowFollowing = true;
                    }
                }
                catch (e) {
                }
            }
            if (!parentComment) {
                this._qcmtsAry.push(newComment);
            }
            else {
                parentComment.AddChildComment(newComment);
            }
            onSuccess(newComment, isNowFollowing);
        };
        if (Common.isWeb()) {
            Ajax.postAsXml(url, qMsgElem, postProcess.bind(this), Common.doNothing);
        }
        else {
            Ajax.queueXmlToServer(url, qMsgElem);
            postProcess.call(this, null);
        }
    };
    return Comments;
}());




// ReferralLink.js

//xnclude "AddressBook.js"
//xnclude "ScreenDoor.js"
//xnclude "Utf8.js"
/// <reference path="Window.d.ts" />
/// <reference path="AddressBook.ts" />
/// <reference path="QSettingsOne.ts" />
/// <reference path="IQSettings.d.ts" />
var ReferralLink = (function () {
    function ReferralLink() {
        this.emailBody = '';
        this.ReferralURI = '';
        this.isSendingRefer = false;
        this.title = '';
        this.dfid = null;
        this.emailTemplate = 'referral_for_player';
        this.body = '';
        this.subject = '';
        this.restartAfterRefer = false;
        this.supportsMailTo = true;
        this.iframe = null;
        this.toEmail = '';
        this.fullsubject = null;
        this.brand = null;
        this.addressBook = {};
    }
    ReferralLink.prototype.setEmailBody = function (text) {
        this.emailBody = text;
    };
    ReferralLink.prototype.getEmailBody = function () {
        return this.emailBody;
    };
    ReferralLink.prototype.getSupportsMailTo = function () {
        return this.supportsMailTo;
    };
    ReferralLink.prototype.setSupportsMailTo = function (value) {
        this.supportsMailTo = value;
    };
    ReferralLink.prototype.setEmailTemplate = function (template) {
        this.emailTemplate = template;
    };
    ReferralLink.prototype.getEmailTemplate = function () {
        return this.emailTemplate;
    };
    ReferralLink.prototype.setReferralTitle = function (title) {
        this.title = title;
    };
    ReferralLink.prototype.getReferralTitle = function () {
        return this.title;
    };
    ReferralLink.prototype.setReferralDfid = function (dfid) {
        this.dfid = dfid;
    };
    ReferralLink.prototype.getReferralDfid = function () {
        return this.dfid;
    };
    ReferralLink.prototype.setReferralURI = function (uri) {
        this.ReferralURI = uri;
    };
    ReferralLink.prototype.getReferralURI = function () {
        return this.ReferralURI;
    };
    ReferralLink.prototype.setReferralToEmail = function (toEmail) {
        this.toEmail = toEmail;
    };
    ReferralLink.prototype.getReferralToEmail = function () {
        return this.toEmail;
    };
    ReferralLink.prototype.ReferByEmail = function () {
        var body = this.body;
        var subject = this.subject;
        var top = window.top;
        top.location = "mailto:?Subject=" + encodeURIComponent(subject) + "&Body=" + encodeURIComponent(body);
    };
    ReferralLink.prototype.returnFocusToTop = function () {
        var item = q$('discussionMembersList_chzn');
        if (item) {
            var inputField = item.getElement('input');
            if (inputField)
                inputField.focus();
        }
    };
    /**
     *
     * @param {QModalDialog} dlgElt
     * @param {boolean} hideTitle hide/show the dialog title (by default the title is shown)
     */
    ReferralLink.prototype.show = function (dlgElt, hideTitle) {
        var src = QSettings.getReferralDialog(this.getReferralTitle(), this.getReferralURI(), this.getEmailTemplate(), this.getEmailBody(), this.getSupportsMailTo().toString(), this.getReferralDfid());
        this.pausePlayerForReferral();
        var myHeight = QSTR.referralHeightNonLatin;
        if (this.getSupportsMailTo()) {
            myHeight = QSTR.referralHeightLatin;
        }
        dlgElt = dlgElt || ReferralQmd.referDialog;
        dlgElt.setContent(src);
        dlgElt.setHeight(myHeight);
        dlgElt.showTitle(hideTitle !== true);
        var self = this;
        function resetReferral() {
            self.resumePlayerAfterReferral();
            Common.chide('referOptionsContainer');
            if (self.refreshAddressBook) {
                self.refreshAddressBook();
            }
            return true;
        }
        dlgElt.show(null, resetReferral);
    };
    ReferralLink.prototype.pausePlayerForReferral = function () {
        if (q$('playPause') == null)
            return;
        var df = Common.currentDfInPlayer();
        if (df) {
            var stateMgr = df.getStateManager();
            if (stateMgr) {
                if (stateMgr.isAudioPlaying()) {
                    this.restartAfterRefer = true;
                    stateMgr.setAudioPlaying(false);
                }
            }
        }
    };
    ReferralLink.prototype.resumePlayerAfterReferral = function () {
        var df = Common.currentDfInPlayer();
        if (!df)
            return;
        var stateMgr = df.getStateManager();
        if (stateMgr) {
            if (this.restartAfterRefer) {
                stateMgr.setAudioPlaying(true);
                this.restartAfterRefer = false;
            }
            stateMgr.ResumePresentation();
        }
    };
    ReferralLink.prototype.getReferralLink = function () {
        var uValue = ScreenDoor.To(ScreenDoor.From(gQCredentials.ScreenDoorName) - 1111);
        return "http://" + QSettings._domainFull + this.ReferralURI + "?u=" + uValue;
    };
    ReferralLink.prototype.getEmail = function (onReady) {
        var myMsg = sprintf(this.getEmailBody(), this.getReferralTitle());
        var ebelt = q$('emailBody');
        if (ebelt) {
            ebelt.value = myMsg;
        }
        var postUrl = QSettings.postUrl();
        var xmlDoc = XML.CreateDocument("<qmsg></qmsg>");
        var qMsgElem = xmlDoc.documentElement;
        qMsgElem.setAttribute("cmd", "getEmail");
        qMsgElem.setAttribute("emailCode", this.emailTemplate);
        var params = xmlDoc.createElement("params");
        qMsgElem.appendChild(params);
        var param = xmlDoc.createElement("param");
        param.setAttribute("key", "<title>");
        param.setAttribute("value", this.getReferralTitle());
        params.appendChild(param);
        param = xmlDoc.createElement("param");
        param.setAttribute("key", "<link>");
        param.setAttribute("value", this.getReferralLink());
        params.appendChild(param);
        param = xmlDoc.createElement("param");
        param.setAttribute("key", "<dfid>");
        param.setAttribute("value", this.getReferralDfid());
        params.appendChild(param);
        param = xmlDoc.createElement("param");
        param.setAttribute("key", "<toEmail>");
        param.setAttribute("value", this.getReferralToEmail());
        params.appendChild(param);
        if (this.fullsubject) {
            param = xmlDoc.createElement("param");
            param.setAttribute("key", "<fullsubject>");
            param.setAttribute("value", this.fullsubject);
            params.appendChild(param);
        }
        if (this.brand) {
            param = xmlDoc.createElement("param");
            param.setAttribute("key", "<brand>");
            param.setAttribute("value", this.brand);
            params.appendChild(param);
        }
        param = xmlDoc.createElement("param");
        param.setAttribute("key", "<fullname>");
        param.setAttribute("value", AccountInfo.FullName);
        params.appendChild(param);
        param = xmlDoc.createElement("param");
        param.setAttribute("key", "<users_message>");
        param.setAttribute("value", myMsg);
        params.appendChild(param);
        var self = this;
        Ajax.postAsXml(postUrl, qMsgElem, function (resp) {
            var doc = XML.CreateDocument(resp);
            var elem = doc.documentElement;
            self.body = XML.findAndFillValueOneLevel(elem, "body");
            self.subject = XML.findAndFillValueOneLevel(elem, "subject");
            if (onReady)
                onReady();
        }, function (status, statusText) {
            alert("Error getting email: " + statusText);
            if (onReady)
                onReady();
        });
        $$$('referByCopyAndPaste').value = this.getReferralLink();
    };
    ReferralLink.prototype.refreshAddressBook = function () {
        var abook = q$('addressBook');
        var addrBkDelBtnElt = q$('addressBookDeleteButton');
        if (!abook)
            return;
        if (addrBkDelBtnElt)
            addrBkDelBtnElt.addClass('disabledButton');
        abook.set('html', '');
        var url = QSettings.buildUrlCmd("getaugmentedaddressbook");
        var self = this;
        Ajax.getText(url, function (jsonData) {
            var addrBook = new AddressBook(jsonData);
            var newSpan;
            var abook = q$('addressBook');
            self.addressBook = {};
            var tempBook = [];
            var entries = addrBook.getAddresses();
            if (!entries)
                entries = [];
            if (entries.length === 0) {
                newSpan = q$(document.createElement('span'));
                newSpan.set('html', QSTR.noEmailAddressesSaved);
                newSpan = q$(newSpan);
                abook.appendChild(newSpan);
            }
            var separator = '\u0000';
            for (var i = 0; i < entries.length; ++i) {
                var entry = entries[i];
                var text = entry.email;
                var value = entry.optionValue;
                self.addressBook[value] = value;
                tempBook.push(text + separator + value);
            }
            tempBook.sort();
            for (var i = 0; i < tempBook.length; ++i) {
                var textAndValue = tempBook[i].split(separator);
                var newCheckBox = q$(document.createElement('input'));
                newCheckBox.setAttribute('type', 'checkbox');
                newCheckBox.setAttribute('value', textAndValue[1]);
                newCheckBox.setAttribute('id', 'abCheck' + i);
                newCheckBox = q$(newCheckBox);
                newCheckBox.addEvent('click', function (event) {
                    // ??? self.updateSelectAllState();
                });
                newCheckBox.addEvent('change', function (event) {
                    // ??? self.updateSelectAllState();
                });
                newSpan = q$(document.createElement('span'));
                newSpan.setAttribute('id', 'abSpan' + i);
                newSpan.set('html', textAndValue[0]);
                newSpan = q$(newSpan);
                newSpan.addEvent('click', function (event) {
                    var id = event.target.id;
                    var i = id.substring(6);
                    var chkElt = q$('abCheck' + i);
                    chkElt.checked = !chkElt.checked;
                    // ??? self.updateSelectAllState();
                });
                newSpan.addEvent('mouseover', function (event) {
                    event.target.addClass('hover');
                });
                newSpan.addEvent('mouseout', function (event) {
                    event.target.removeClass('hover');
                });
                var newDiv = q$(document.createElement('div'));
                newDiv.addClass('addressBookEntry');
                newDiv = q$(newDiv);
                newDiv.appendChild(newCheckBox);
                newDiv.appendChild(newSpan);
                abook.appendChild(newDiv);
            }
        });
    };
    return ReferralLink;
}());
var referral = new ReferralLink();

//include "AddressBook.js"
//include "ScreenDoor.js"
//include "Utf8.js"



// TabbedPagelet.js

/// <reference path="mootools.d.ts" />
var TabbedPagelet = (function () {
    function TabbedPagelet() {
    }
    TabbedPagelet.ToggleTab = function (groupID, itemID, numberOfTabs) {
        var clickedTab = q$('tabTitle' + groupID + itemID);
        if (clickedTab.hasClass('open')) {
            clickedTab.removeClass('open');
            Common.chide('tabContent' + groupID + itemID);
        }
        else {
            // close other tabs
            for (var i = 0; i < numberOfTabs - 1; i++) {
                if (i != itemID && q$('tabTitle' + groupID + i) != null) {
                    q$('tabTitle' + groupID + i).removeClass('open');
                    Common.chide('tabContent' + groupID + i);
                }
            }
            // open the one clicked on
            clickedTab.addClass('open');
            Common.cshow('tabContent' + groupID + itemID);
        }
    };
    TabbedPagelet.SelectTab = function (tabId, tabIndex) {
        var currentTab = TabbedPagelet.SelectedTab(tabId);
        if (currentTab != tabIndex) {
            var currentTabTitle = q$('tabTitle' + tabId + "" + currentTab);
            var nextTabTitle = q$('tabTitle' + tabId + "" + tabIndex);
            var tabContents = q$('tabContents' + tabId);
            q$(currentTabTitle).removeClass('selectedTitle');
            q$(nextTabTitle).addClass('selectedTitle');
            var idval = tabId + "" + tabIndex;
            q$(tabContents).innerHTML = TabbedPagelet.TabContents[idval];
            TabbedPagelet[tabId] = tabIndex;
            TabbedPagelet.HandleElementXX(tabContents);
        }
    };
    TabbedPagelet.SelectedTab = function (tabId) {
        if (!TabbedPagelet[tabId])
            TabbedPagelet[tabId] = 0;
        return TabbedPagelet[tabId];
    };
    // used to be in "NewHtmlHandler"
    TabbedPagelet.HandleElementXX = function (e) {
        if (typeof PopupPreview !== 'undefined' && PopupPreview.Update) {
            PopupPreview.Update(e);
        }
        if (typeof HoverStates !== 'undefined' && HoverStates.addHoverFunctions) {
            HoverStates.addHoverFunctions(e);
        }
    };
    TabbedPagelet.TabContents = {};
    return TabbedPagelet;
}());




// DesktopBrowserIFace.js

///<reference path="../appIFace/AppIFace.d.ts"/>
///<reference path="../search/SearchCmdsDesktop.ts"/>
var DesktopBrowserIFace = (function () {
    function DesktopBrowserIFace() {
        this.hasStarted = false;
        this._lastTextDialogValue = "";
        this._currentPanelName = "";
    }
    DesktopBrowserIFace.prototype.getOS = function () {
        return "web";
    };
    DesktopBrowserIFace.prototype.onDOMContentLoaded = function () {
    };
    DesktopBrowserIFace.prototype.viewDataform = function (dfid, ns, isSecure, urlToShowAfter, webUrl, trackingInfo) {
        if (trackingInfo) {
            Common.LD(trackingInfo);
        }
        document.location.href = webUrl;
    };
    DesktopBrowserIFace.prototype.viewDataform2 = function (dfid, ns, isSecure, urlToShowAfter, webUrl, trackingInfo, gtmTrigger) {
        if (gtmTrigger) {
            Common.addDataLayerClickEvent(gtmTrigger);
        }
        if (trackingInfo) {
            Common.LD(trackingInfo);
        }
        document.location.href = webUrl;
    };
    DesktopBrowserIFace.prototype.onScreenShapeChange = function () {
    };
    DesktopBrowserIFace.prototype.onVisibilityChange = function () {
    };
    DesktopBrowserIFace.prototype.viewPeerMessage = function (dfid, ns, requiresTimeout, webUrl, trackingInfo) {
        // alwys shown on Inbox Page in desktop
        if (trackingInfo) {
            Common.LD(trackingInfo);
        }
        if (document.location.href.indexOf('inbox') > 0)
            PeerMessageInbox.displaySelectedMsg(dfid);
        else
            document.location.href = webUrl;
    };
    DesktopBrowserIFace.prototype.postCommand = function (command, subCommand) {
        Common.addDebugStr("DesktopBrowserIFace: Attempt to call postCommand");
    };
    DesktopBrowserIFace.prototype.handleError = function (errorMessage) {
        alert(sprintf(QSTR.errorGeneric, errorMessage));
    };
    DesktopBrowserIFace.prototype.getAppName = function () {
        return "qmd_fakeweb";
    };
    DesktopBrowserIFace.prototype.supportsSettings = function () {
        return false;
    };
    DesktopBrowserIFace.prototype.getSettingAsync = function (key, callback) {
        callback(null);
    };
    DesktopBrowserIFace.prototype.setSetting = function (key, value) {
    };
    DesktopBrowserIFace.prototype.initializeSearch = function () {
        window.SearchCmds = new SearchCmdsDesktop();
    };
    DesktopBrowserIFace.prototype.showTextDialog = function (curPanelName, prompttxt, hint, text, jsToEValOnComplete, isMultiline, isNumber) {
        if (curPanelName)
            this._currentPanelName = curPanelName;
        var v = prompt(prompttxt, text || hint);
        if (v) {
            this._lastTextDialogValue = v;
            eval(jsToEValOnComplete);
        }
    };
    DesktopBrowserIFace.prototype.getLastTextDialogResult = function () {
        return this._lastTextDialogValue;
    };
    DesktopBrowserIFace.prototype.showRatingDialog = function (prompt, rating, onComplete) {
    };
    DesktopBrowserIFace.prototype.getLastRatingDialogResult = function () {
        return 0;
    };
    DesktopBrowserIFace.prototype.getCurrentPanelName = function () {
        return this._currentPanelName;
    };
    DesktopBrowserIFace.prototype.setCurrentPanelName = function (name) {
        this._currentPanelName = name;
    };
    return DesktopBrowserIFace;
}());
var theAppIFace = new DesktopBrowserIFace();
document.addEventListener("DOMContentLoaded", theAppIFace.onDOMContentLoaded.bind(theAppIFace), false);

