Server/Code/modifications to main.js

From kJams Wiki
Jump to navigation Jump to search

Often times when using kJams Server, the user will miss the "Song Added" alert at the bottom of the window. (Heck, even I just recently noticed it!) As a result, they will mistakenly hit the "Tonight" button over and over, thus adding the song multiple times. To combat this (but not be quite as intrusive as a pop up alert) I made this little code snippet that will make the text bright red and flash it several times to catch the users attention.

To use it, open the file "main.js" (it should be in "~/Libraries/Preferences/kJams/server") and find the "function m_setStatus(status, revert)" code block. Replace it with the text below and save.

function m_setStatus(status, revert) {
	statusObj = document.getElementById("status");
	statusObj.innerHTML = "<span style='color:#FF0000'>" + status + "</span>";
	var newInnerHTML='statusObj.innerHTML = "<span style="color:#FF0000">" + status + "</span>"';
	blink();
	setTimeout("statusObj.innerHTML = newInnerHTML",1250);
}

function blink(){ 
blinkFlag = 1 
blinkCount = 1 
blinkTimer(); 
}

function blinkTimer(){ 
if(blinkFlag==1){
blinkSpeed=250
blinkNumber=10 //If this value is even, the text flashes then remains visible. If it is odd, it flashes, then disappears
blinkFlag=0; 
blinkCount++; 
document.getElementById("status").style.visibility='visible'; 
}else { 
blinkFlag=1; 
blinkCount++; 
document.getElementById("status").style.visibility='hidden'; 
} 
if (blinkCount < blinkNumber) {setTimeout('blinkTimer()', blinkSpeed);} 
} 

In addition, it is very useful to trap the delete key, so that users do not inadvertently go back to the previous page by hitting this key (which, for instance, might take them back to the previous singers page from the login screen after a log out). This would be bad! To do this, you need to make a few mods to the pages. In particular, you need to call the function in your pages. To make it work, paste this into the variable declaration section of your main.js (at the top).

//checks to see if the search field it in focus. If it is, allow the user to use the Delete/Backspace key. Otherwise, set flag to trap it.
var inSearch = {
   on: function() {allowBackspace = true;},
   off: function() {allowBackspace = false;}
}

And then add this somewhere in the function declarations:

function trapDelete() {
	//Checks to see if the key pressed is the Delete/Backspace key, and if so, stop it from getting to the browser.
   var keyID = (window.event) ? event.keyCode : e.keyCode;
   if (keyID==8 && !allowBackspace){
	  return false;
   }
   return true;
}

Then you can just add the following code into the javascript section of your other pages:

	//Bind key press function
	document.onkeyup = m_keyPressed;
	//Prevent browser from seeing the Delete key press
	document.onkeydown=trapDelete;

Alternately, you can just use the entire main.js file from the previous page.

Lastly, it is probably undesirable in a kiosk-type session to allow the person to close the window on your laptops, thus making the machine useless for the next user. To block this, I added the following code:

Add this to the script section of your mainscreen.html file (and any other page you want to stop the user from closing:

    //function triggered by any closing of the current document
    function confirmUnload(){ 
        if(!allowUnload){
            //message displayed (as well as inbuilt IE junk) when page is unloaded.
            return 'Why on earth would you think it is a good idea to close this window?!? Well, it ISN\'T!!! Do NOT close this window. If you do, all hell will rain down upon you, you will cause a micro-singularity to destroy the known universe, and I will get very upset. (At you closing the window, not the destruction of the universe, that can fend for itself.)\n :\'(';
        }
    }

Then add the following lines to the function m_sessionLogout function of your main.js

	// Sets the flag to tell confirmUnload subroutine that it is OK to let the user leave this page (close the Window, etc.)
	allowUnload = true;

If you want to force users to use both first and last names (useful if you use server heavily, since otherwise you will very quickly have name conflicts, at least in your history, if not in your tonights) you can use the following modified newsinger.html code. In addition, the new code puts instructions in the various fields, in particular that password field (since some people seem to have a hard time figuring out that what they have to do). For those interested, it was necessary to use a bit of a hack here. Normally the password field is encoded, so that when you type in characters, they get represented as "•" bullets (to prevent people from seeing the password being entered). But one consequence of this is that any text you put in the field to prompt users gets changed to bullets too. So the code I added tricks the browser engine into thinking, just for a moment as it is being drawn, that it is NOT a password field (by actually making it a normal text field, and then, after the guide text is placed, changing it back to a password field, out from under the browser.

<html>
	<head>
		<meta http-equiv=Content-Type content="text/html; charset=UTF-8">
		<title>kJams New Singer</title>
		
		<script src="common.js"></script>
		<script src="./spry/xpath.js"></script>
		<script src="./spry/SpryData.js"></script>
		<script src="data.js"></script>
		<script type="text/javascript">
			function catname(){
				var firstname = document.forms[0].singerfirstname.value;
				var lastname = document.forms[0].singerlastname.value;
				document.forms[0].singername.value = firstname + " " + lastname;
			}
			function validate(thisform) {
				with (thisform){
					if (singerfirstname.value=='') {
						alert('Hey, unless you\’re Obama, ya gotta give me a first name too. Try again.');
						event.returnValue=false;
					}
					else if (singerlastname.value=='Required!') {
						alert('What, you think you\’re Madonna? A last name is required. Lets try this again..');
						event.returnValue=false;
					}
						//safe to navigate away from this page
				}
			}
						    //variable to control if message is shown
    var allowUnload = false;
  
    //function triggered by any closing of the current document
    function confirmUnload(){ 
        if(!allowUnload){
            //message displayed (as well as inbuilt IE junk) when page is unloaded.
            return 'Why on earth would you think it is a good idea to close this window?!? Well, it ISN\'T!!! Do NOT close this window. If you do, all hell will rain down upon you, you will get A.I.D.S., and I will get very upset. (At you closing the window, not the A.I.D.S..)\n:\'(';
        }
    }

    //register function with the event handler
    window.onbeforeunload = confirmUnload;
		</script>
		
		<style type="text/css">
			#main {
				width: 400px;
				margin-left: auto;
				margin-right: auto;
				text-align: center;
				background: url('metal.jpg');
				border-style: solid;
				border-color: #000000;
				border-width: 1px;
			}
			
			#main p {
				font-size: 24pt;
			}
			
			#main table {
				margin-left: auto;
				margin-right: auto;
			}
			
			#main img {
				margin-bottom: 10px;
			}
		</style>
	</head>
	
	<body>
		<div id="main">
			<p>New Singer</p>
			<img src="kjams.png" /><br />
			<font color="#FF0000"></font>
			<form id="form" method="POST" action="" onsubmit="validate(this); allowUnload=true">
				<table>
					<input type="hidden" id="singername" name="singername">
					<tr><td>First Name: </td><td><input type="text" name="singerfirstname" value="" onkeyup="catname()"/></td></tr>
					<tr><td>Last Name: </td><td><input type="text" name="singerlastname" value="Required!" onfocus="this.value= (this.value=='Required!') ? '' : this.value" onBlur="this.value= (this.value=='') ? 'Required!' : this.value" onkeyup="catname()"/></td></tr>
					<tr><td>Password: </td><td><input type="password" name="password" id="password" /></td></tr>
<script type="text/javascript">
var p = document.getElementById('password');
p.type = 'text';
p.value = 'Make a password';
p.onfocus = function() {
if (this.type == 'text') {
this.value = '';
this.type = 'password';
this.focus();
}
}
</script>
					<tr><td>Again: </td><td><input type="password" name="confirm" value="" /></td></tr>
					<tr><th colspan="2"><input type="submit"  name="submit" value="Jam Out!" /></th></tr>
				</table>
			</form>
			<p style="font-size: 12pt;">[ <a href="/" onClick="allowUnload=true">Back</a> ]</p>
		</div>
		
		<script language="javascript">
			document.getElementById("form").action = url_newsinger;
		</script>
	</body>
</html>

Another recurring issue is that many people don't seem to understand the entire paradigm, and insist on adding themselves as a new singer every time they want to add a new song. To help prevent that, I added an extra confirmation step to try to get across the fact that this is not helpful. Try the modified login screen code below:

<html>
	<head>
		<title>kJams Login</title>
		
		<script src="common.js"></script>
		<script src="./spry/xpath.js"></script>
		<script src="./spry/SpryData.js"></script>
		<script src="data.js"></script>
		
		<script type="text/javascript">
			function iPhoneAlert() {

				if ((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))) {
					var question = confirm("You need iJams to log in!")

					if (question) {
						window.location = "http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=301301004&mt=8";
					}
				}
			}

			    //variable to control if message is shown
    var allowUnload = false;
  
    //function triggered by any closing of the current document
    function confirmUnload(){ 
        if(!allowUnload){
            //message displayed (as well as inbuilt IE junk) when page is unloaded.
            return 'Why on earth would you think it is a good idea to close this window?!? Well, it ISN\'T!!! Do NOT close this window. If you do, all hell will rain down upon you, you will get A.I.D.S., and I will get very upset. (At you closing the window, not the A.I.D.S..)\n :\'(';
        }
    }

    //register function with the event handler
    window.onbeforeunload = confirmUnload;
		</script>
		
		<style type="text/css">
			#main {
				width: 400px;
				margin-left: auto;
				margin-right: auto;
				text-align: center;
				background: url('metal.jpg');
				border-style: solid;
				border-color: #000000;
				border-width: 1px;
			}
			
			#main p {
				font-size: 24pt;
			}
			
			#main table {
				margin-left: auto;
				margin-right: auto;
			}
			
			#main img {
				margin-bottom: 10px;
			}
		</style>
	</head>
	
	<body onLoad="iPhoneAlert();">
		<div id="main">
			<p>Singer Login</p>
			<img src="kjams.png" />
			<form id="form" method="POST" action="" onSubmit="allowUnload=true">
				<table>
					<tr><td>Singer: </td><td id="singers">Please wait...</td></tr>
					<tr><td>Password: </td><td><input type="password" name="password"></td></tr>
					<tr><th colspan="2"><input type="submit"  name="submit" value="Login" /> <input type="button" onClick="goNewSinger(); allowUnload=true;" value="New Singer" /></th></tr>
				</table>
			</form>
			<div>[ <a id="helplink" onClick="allowUnload=true" href="">Help</a> ]</div><br />
		</div>
		
		<script language="javascript">
			document.getElementById("form").action = url_main;
			document.getElementById("helplink").href = url_help;
			
			getSingers(url_singers, populateSingers);
			function populateSingers(singers) {
				var selectObj	= document.createElement("SELECT");
				var optgroupObj	= document.createElement("OPTGROUP");
				
				selectObj.name = "singer";
				selectObj.style.width = "100%";
				
				optgroupObj.label = "";
				
				for (var i = 0; i < singers.length; i++) {
					if (singers[i]['name'][0].toUpperCase() != optgroupObj.label) {
						optgroupObj			= document.createElement("OPTGROUP");
						optgroupObj.label	= singers[i]['name'][0].toUpperCase();
						
						selectObj.appendChild(optgroupObj);
					}
					
					var optionObj = document.createElement("OPTION");
					optionObj.value = singers[i]['id'];
					optionObj.innerHTML = singers[i]['name'];
					optgroupObj.appendChild(optionObj);
				}
				
				document.getElementById("singers").innerHTML = "";
				document.getElementById("singers").appendChild(selectObj);
			}
			
			function goNewSinger(){
			
				var newSingerConfirm=prompt("HEY YOU.\n\nREAD THIS DIALOGUE BOX ALL THE WAY THROUGH!!!:\n\nOnly add yourself if you have never, EVER sung with me before. If you have EVER sung with me before, even if it was a two years ago, even if your name is not in the list, but you think it should be, PLEASE do not add yourself again. Instead, come see me to add your name to the system.  If you really ARE a new singer, however, type in the value of equation","2+3=?");
				if (newSingerConfirm == "5")
					{
					window.location=url_newsinger;
					}
				else
					{
					window.location=url_loginscreen;
					}
			}
			
		</script>
	</body>
</html>

Feel free to modify the confirmation text as you see fit.