JavaScript - Help Creating Dynamic Buttons From Array
Hey all! So there I was newly hired and tasked with pouring through someone else's code to see what could be modified and brought up to date. After successfully finding the errors and correcting them and fulfilling the tasks my new supervisor assigned me, he slaps me on the back and says, "Well done! Now make it dynamic!" By which he meant the chapter buttons I spent hours creating from the existing code.
Here's what he wants: the old code has an array, we'll call it someArray, that is assigned its values by the instructional developer as html pages are added to the course. So for example the code might look like this, Code: var someArray = new Array(4); someArray[0] = "video1/video1.html"; someArray[1] = "video2/video2.html"; someArray[2] = "video3/video3.html"; Now, each page has an associated chapter button. So video1/video1.html would have ch1Btn, video2/video2.html would have ch2Btn and so forth. Each button in turn calls a specific function which does only one thing - sets the currentPage variable to page associated with that button/array contents. For example, I have created the following functions to call each page: Code: function doCh1(){currentPage = 0; goToPage();} function doCh2(){currentPage = 1; goToPage();} function doCh3(){currentPage = 2; goToPage();} I should mention that all this is being done from within an html wrapper that calls each page into an iframe. The currentPage variable is assigned the url of one of the elements from the pageArray. My supervisor wants to be able to manually add pages to the pageArray and have the javascript code generate the associated buttons and function calls so when the learner clicks on one of the dynamically created buttons, s/he is taken to the correct page. Currently I'm using static images with the onclick calling the correct function to set my currentPage value and send the learner on his/her merry way. Is there a way to do all of this dynamically? If so, can you help me get my head around this by providing some examples? Sorry for the long post. Thank you, M Similar TutorialsHi, I searched the web for a button that can be animated, as well as dynamic. but I couldn't find one, so I decided to try my hand at creating one. My method is similar to a post made by Bram2: http://codingforums.com/showthread.php?t=153326, however, I have found my code to be unreliable and it doesn't apply only to the area where the table is, instead of spreading across the screen. The reason for trying to create a button this way is because I'm lazy, I don't want to create a new button in a graphics editor, spending hours trying to make it uniform with the rest of the buttons on the page, every time I want a new button. Doing it this way will also enable to have buttons with mulitple lines of text. I am fairly new to javascript, so I am wondering if anyone can give me a hand making it more reliable or pointing me to a script that has already been created. I put the button Here instead of filling the post with code. Please look at it before telling me it can be done with the <button> tag, because I tried before posting here. thanks, grayatrox Edit:I have managed to get the code to do what I wanted it to do, and more efficently too. Old code is commented out in the orginal webpage. This is a working example on how to impliment the buttons. javascript: Code: /* Notes: - Each button MUST have a unique name. - You may need to create a secondary function that the button can activate like I did with the go(url) function below. - Email me (grayatrox) at 238atrox@gmail.com for bugs, or to suggest improvements. - Yes I know tables within tables is bad, if you read through my code carefully you will see where I am talking about. */ function loadButton() { //preload the buttons. image1 = new Image(); image1.src = "images/button_up_L.png"; //button up left image2 = new Image(); image2.src = "images/button_up_C.png"; //button up centre image3 = new Image(); image3.src = "images/button_up_R.png"; //button up right image4 = new Image(); image4.src = "images/button_down_L.png"; //button down left image5 = new Image(); image5.src = "images/button_down_C.png"; //button down centre image6 = new Image(); image6.src = "images/button_down_R.png"; //button down right } function createButton(buttonName, buttonText, buttonAction, id) { // create the code for a button output= "<table border='0' cellpadding='0' cellspacing='0' id="+buttonName+">"; output=output+"<tr name="+buttonName+" onclick=\""+buttonAction+"\" onmouseover=\"changeButton('down', '"+buttonName+"')\" onmouseout=\"changeButton('up', '"+buttonName+"')\">"; output=output+"<td align='right'><img id='"+buttonName+"_leftImage' src='images/button_up_L.png'/></td>"; output=output+"<td id='"+buttonName+"_middleImage' align='middle' background='images/button_up_C.png'/>"+buttonText+"</td>"; output=output+"<td align='left'><img id='"+buttonName+"_rightImage' src='images/button_up_R.png'/></td>"; output=output+"</tr>"; output=output+"</table>"; return output; } function writeButton(buttonName, buttonText, buttonAction) { // write button immediatly below where function has been called document.write(createButton(buttonName, buttonText, buttonAction)); } function writeButtonInId(buttonName, buttonText, buttonAction, id) { // write the button in an id document.getElementById(id).innerHTML=createButton(buttonName, buttonText, buttonAction); } function changeButton(action, name) { // button animation if (action== "up") { document.getElementById(name+'_leftImage').src="images/button_up_L.png"; document.getElementById(name+'_middleImage').style.backgroundImage ="url(images/button_up_C.png)"; document.getElementById(name+'_rightImage').src="images/button_up_R.png"; } else if (action== "down") { document.getElementById(name+'_leftImage').src="images/button_down_L.png"; document.getElementById(name+'_middleImage').style.backgroundImage ="url(images/button_down_C.png)"; document.getElementById(name+'_rightImage').src="images/button_down_R.png"; } } function go(url) { // written becuase there were too many ' and ". You can do this for any javascript function (I hope) document.location=url; } Everything works but I'm afraid that it might be slow due to my heavy use of setAttribute for my dynamically created buttons. This is the only place I've needed it because I was able to use this bit of code Old Pedant came up with. Here's what I'm trying to improve upon Code: span.setAttribute("onMouseOver","ShowPage(type_num,\"all\",1);ShowPage(type_num,\"y"+z+"\",1);"); Quote: Originally Posted by Old Pedant Code: xxx.setAttribute("itemnum",itemnum); xxx.onclick = function() { return showRapidText(this.getAttribute("itemnum")); }; I don't understand how to apply that ^ to this > Code: span.setAttribute("onMouseOver","ShowPage(type_num,\"all\",1);ShowPage(type_num,\"y"+z+"\",1);"); My working version is here ... and the next bit is what I've tried and had no success with. Code: for (z=1920; z<=2010;z++){ var li = document.getElementById("Dynamic_Year_Filter_Reference"); var span = document.createElement("SPAN"); var text = document.createTextNode(z); span.id = "y"+z+"_mainmenuimg" span.className = "mainmenuimgyear" span.setAttribute("onMouseOver","ShowPage(type_num,\"all\",1);ShowPage(type_num,\"y"+z+"\",1);"); span.setAttribute("onMouseDown","l_num=\"y"+z+"\";pg_num=1;ShowPage(type_num,l_num,pg_num);"); span.setAttribute("onMouseOut","ShowPage(type_num,l_num,pg_num);"); li.appendChild(span).appendChild(text) } } Code: span.setAttribute("type_num", type_num); span.onmouseover = function() { ShowPage(this.getAttribute("type_num"),"all",1);ShowPage(this.getAttribute("type_num"),"y"+z+"",1); }; I am developing a site that adds multiple dynamic buttons. I would be ideal if the event these buttons trigger could pass a 'variable' (the passed variable is constant with respect to each button). My attempt... myButton.setAttribute("onClick", "myFunction(" + myVar +")"); ...doesn't seem to work. Can anyone help out? Hi, I have an HTML table dynamically populated with data from a coldfusion query and having radio buttons - see code following below. I need javascript to see the radio buttons and the user's selection - "approved"; "denied"; or, "N/A". If the user selects "approved" for multiple rows and then Submit the information will update the database table and remove those rows. However, if the user selects "approved" and "denied" then I need to update the "approved" rows and stop the update at the "denied" row and show a dialog box which informs the user that the "Reason for Denial" text box must be entered. Then the Submit button can be engaged and the "denied" selection processed. Only one "denied" at a time will be updated - but all "approved" entries can be denied similtaneously - unless a "denied" intervenes. I do have javascript code for the "denied" selection with empty "Reason for Denial" text box - see below: Code: <script type="text/javascript"> function rationale() { var denInfo = document.getElementById("denialReason"); if(denInfo.value == ""){ alert("Please enter reason for denial in Rationale for Request Denial"); return false; denInfo.focus(); } } </script> The overall action seems like it would need some extensive javascript coding and I haven't a clue how to do it. Any help is GREATLY APPRECIATED. Code: <table border="1" cellspacing="1" cellpadding="2" style="position:relative; left:50px;" width="1000"> <tr> <td width="140" align="center" bgcolor="#FEF9E7"><font color="#0000FF" style="font-weight:bold;"> Name<hr />Begin Date</font></td> <td width="75" align="center" bgcolor="#FEF9E7"><font color="#0000FF" style="font-weight:bold;"> Request Date<hr />End Date</font></td> <td width="145" align="center" bgcolor="#FEF9E7"><font color="#0000FF" style="font-weight:bold;">Type of Hrs<hr />Request Justification</font></td> <td width="76" align="center" bgcolor="#FEF9E7"><font color="#0000FF" style="font-weight:bold;"> Num Hrs Req<hr />Rel Comp Begin Date</font></td> <td width="98" align="center" bgcolor="#FEF9E7"><font color="#0000FF" style="font-weight:bold;"> Projects<hr />Rel Comp End Date</font></td> <td width="180" align="center" bgcolor="#FEF9E7"><font color="#0000FF" style="font-weight:bold;"> Decision<hr />Leave Slip Submitted</font></td> </tr> <cfoutput query="Req"> <tr style="background-color:'FFFFFF';" onMouseOver="this.style.backgroundColor='FFCC33';" onMouseOut="this.style.backgroundColor='FFFFFF'" > <td colspan="6"> <table cols="6" border="1" cellpadding="5" cellspacing="0"> <tr> <td width="177"> #Name#</td> <td width="107"> #DateFormat(RequestDate, "m/d/yyyy")#</td> <td width="178"> #TypeofHours#</td> <td width="105"> #NumberHrsRequested#</td> <td width="127"> #project#</td> <td width="218"> #Decision# <cfinput name="Decision_#ID#" id="Decision_#ID#" type="radio" value="approved" size="1">Approve <cfinput name="Decision_#ID#" id="Decision_#ID#" type="radio" value="denied" size="1">Deny <cfinput name="Decision_#ID#" id="Decision_#ID#" type="radio" value="" size="1" checked="yes">N/A </td> </tr> <tr> <td> #DateFormat(BeginDate, "m/d/yyyy")#</td> <td> #DateFormat(EndDate, "m/d/yyyy")#</td> <td> #justification#</td> <td> #DateFormat(RCBDate, "m/d/yyyy")#</td> <td> #DateFormat(RCEDate, "m/d/yyyy")#</td> <td> #RCLeaveSlip#</td> </tr> <tr id="denyRow_#ID#"> <td colspan="1"><font color="##0000FF"; style="font-weight:bold">Reason For Denial</font></td> <td colspan="5"> #ReasonForDenial# <cftextarea name="denial_#ID#" cols="85" rows="3" wrap="hard"/> </td> </tr> </table> </td> </tr> </cfoutput> </table> Thank you, John hi i am newbie to js please help me like a newbie thanks. i want to make a form. the form will have three text fields and with two buttons. what i want with this form is when the user enters the first three fields and if he wants to add more then he will click on add more button and on the same page three more fields will appear below the first three fields. the user will then enter these three fields then if he wants to add more then he will click on add more button. so three more fields will appear below the first six fields. user will enter these fields. he will be allowed to enter upto eight or less than eight times. once he finishes with this then he will click the second button to insert this data into db. Hello, I'm trying to create a webpage where users can click on a dynamically generated set of questions: <?php do { ?> <p><?php echo $row_rsQuestions['question_text']; ?><?php echo $row_rsQuestions['question_type']; ?></p> <?php } while ($row_rsQuestions = mysql_fetch_assoc($rsQuestions)); ?> and by clicking on a particular question, there will be an update for their particular listing of personal questions in a MySql database. I know how to create the database update part, but I think that I would need to javascript to: 1) tell my page that it's time to update (i.e. add a particular question as soon as they click it) 2) pass along the correct variable to the database update portion of the page. Any help on these two items would be appreciated. Thank you! My application reads an array of URLs in Javascript and displays them in a table. I need to create mouseover events for each of the links (just an alert message for now.) I have tried this a few ways, but for each one the mouseover event fires for each link before anything else is loaded on the page, and when the page is loaded, no link is displayed. Here are the two ways I've tried: Code: var cell1 = document.createElement("TD"); cell1.innerHTML = '<A HREF= ' + url + 'onMouseOver="' + alert("my alert box"); + '"> my page </A>'; Code: cell1.innerHTML = '<A HREF= "' + url + '"> my page </A>'; cell1.onMouseOver = alert('alert'); I have also tried many variations of these including: Code: cell1.innerHTML = '<A HREF= "' + url + '"> my page </A>'; cell1.onMouseOver = function(){alert('alert');}; Code: var cell1 = document.createElement("TD"); cell1.innerHTML = '<A HREF= " ' + url + ' " onMouseOver=" alert("my alert box"); "> my page </A>'; But they all yield the same result, so any help would be much appreciated! I've got a table in which I want to have certain elements changeable if the user presses a button. The elements are stored in an array and I want to cycle through them when the button is pressed. Here's a section of what I'm working with so far: Code: <tr> <td valign="top"> <dl> <script type="text/javascript"> var w=0; var s=0; var c=0; var slugga_replace_list = new Array("Slugga","Shoota","Shoota/Rokkit","Shoota/Skorcha","Twin-Linked Shoota"); var choppa_replace_list = new Array("Choppa","Big Choppa","Power Klaw"); var warboss_wargear = new Array(); warboss_wargear[0] = slugga_replace_list[s]; warboss_wargear[1] = choppa_replace_list[c]; warboss_wargear[2] = "Stikkbombz"; for (w=0; w<2; w++) { document.write("<dt><input type='button' name='subtract' value='-' onclick='subtract()'>"+warboss_wargear[w]+"<input type='button' name='add' value='+' onclick='add()'/></dt>"); } function add() { s++ return s; } function subtract() { s-- return s; } </script> </dl> </td> </tr> I've tried using the ++ and -- to change the value of s, but it's not changing the text. Am I in the neighborhood at least? So here's my problem. I have a long list of buttons that I want to declare their onclick with values from an array. It looks something like this. It seems simple but obviously there's something that I'm not seeing that isn't allowing this to run.Here's what the code looks like Code: <html> <body> <form name="form1"> <input type="button" name="one"> <input type="button" name="two"> <input type="button" name="three"> </form> <script> function hello() { .... .... } goodbye = ["one","two","three"] for(i=0;i< 3; i++) { document.form1.goodbye[i].onclick=hello; } If anybody could help me out with this I would greatly appreciate it. Within my project, using PHP/HTML/Javascript, I am trying to set up a page where a corresponding submit button is enabled when a given checkbox is checked. What complicates my attempt is that the checkboxes and submit buttons are in the form of arrays. Here is a snippet of my code: Code: <form name="myform4" id="list_apps" method="post"> <?php for ($i=0; $i<$num_rows;$i++) { ?> <p> <input type="checkbox" name="app[]" id="app[]" onclick="enable_perm()"> <input name="set_perm[]" type="submit" id="set_perm[]" value="Set Permissions"> </p> <?php } </form> Here is my attempt at using Javascript to disable the first submit button after clicking any check box: Code: function enable_perm() { document.myform4.set_perm[0].disabled = true; } What am I missing here, or, how do I enable/disable submit buttons that are part of an array? Hi all, I am a relatively new to javacript and need some help. I have several arrays already defined: array_1 array_2 array_3 etc. I also have a few divs with ids and classes: <div id="1" class="sample"></div> <div id="2" class="sample"></div> <div id="3" class="sample"></div> etc. I am trying to use the class (sample) to run a function: (1) first I get the ID: current_id = $(this).attr("id"); (2) based on the id I want to display the array: alert('array_'+current_id); The problem is I get an alert box with the array name ("array_1") and not the CONTENT of the array. How do i solve this? Thanks!! I am really new to scripting. I found a nice script that copy2clipboard. What I have is the need to create a function array (not sure if that is what it is called) so that i don't need to create a new function everytime i add something to be copied. Anyone have any thoughts on this or a reference i can review to try and figure this out. thanks in advance. Code: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="en"> <head> <script type="text/javascript"> function clipper() { var data = document.getElementById("Data").value; window.clipboardData.setData("Text", data); } function clipper1() { var data1 = document.getElementById("Data1").value; window.clipboardData.setData("Text", data1); } function clipper2() { var data2 = document.getElementById("Data2").value; window.clipboardData.setData("Text", data2); } </script> </head> <body> <span id="Data" value="This is the clipper function."></span><a href="javascript:clipper()">clipper function</a><br> <span id="Data1" value="This is the clipper1 function."></span><a href="javascript:clipper1()">clipper1 function</a><br> <span id="Data2" value="This is the clipper2 function."></span><a href="javascript:clipper2()">clipper2 function</a><br> </body> </html> Hello, I've a checkbox validation script to check for at least one ckeck. Code: <script type="text/javascript"> function chkChecks(){ isChecked=false alert(document.forms["form1"]["checked[]"].length); for(var i=0;i<document.forms["form1"]["checked[]"].length;i++){ if(document.forms["form1"]["checked[]"][i].checked){ isChecked=true } } if(isChecked){ document.forms["form1"].submit() } else{ alert('Please select a checkbox') } } </script> for the form Code: <form name="form1" action="test.php"> <input type="checkbox" name="checked[]" value="1"> <input type="checkbox" name="checked[]" value="2"> <input type="checkbox" name="checked[]" value="3"> <input class="button_140" type="button" value="Check" onclick="chkChecks()"> </form> It works well for more than one checkboxes, but these are generated dynamically by PHP and if there is only one checkbox, document.forms["form1"]["checked[]"].length returns 'undefined'. Can I modify this to work in all cases? thanks, art. I apologize in advance for my ignorance. I'm relatively new to javascript. I am trying to dynamically create a page based on information in a .txt. So far the code works. But only for a spacific line in the .txt. I would like it to create numbered divs and fill with approprate info from .txt for each line in .txt. Does that make sense? Any help you can provide would be greatly appriciated. Oh and I'm not worried about cross browser function this is for intra-net and all clients use Mozilla. P.S.: I will paste full code if necessary and it is explained exactly how. Is it: [ "my code goes here" ] or [code] my code goes here [code] ok so I am trying to create a function that creates an array comprised of filenames based on a given range. I.E if 2-8 is selected and a foldername of UMCP/ and a common name of college is also given, the function should return and array such as [UMCP/college2.jpg,UMCP/college3.jpg.....UMCP/college8.jpg]. Here is what I've got but the alert that should tell me the filename of the first image says it is undefined, how can i fix this? Code: function getArrayPhotosNames (total,count,first,last) { /*window.alert("get Array Photo Names");*/ var folderName = document.getElementById("photofold").value; var Alias = document.getElementById("commonName").value; for (var i=0; i>=total; i+=1) { var imageNum = i+first; var filename = folderName + Alias + imageNum + ".jpg"; window.alert("image will be stored as"+filename); photosArrayGlobal[i]= filename; } window.alert("the first photo is" +photosArrayGlobal[0]); var countnum = count.value; if (count === 0) { window.alert("randomize time") var randomArray = photosArrayGlobal.sort( randomize() ); var randomPhoto= document.getElementById("myImage"); randomPhoto.setAttribute("src", randomArray[photoIndexGlobal]); } else { var firstPhoto=document.getElementById("myImage"); firstPhoto.setAttribute("src", photosArrayGlobal[photoIndexGlobal]) } } Hi I need help with spawning in my game. I have this code: Code: function spawnEnemy() { var shapes = [LeftBlock, RightBlock, middleRightBlock, middleLeftBlock, middleBlock]; var shape = shapes[Math.floor(Math.random() * shapes.length)]; var RandomBlock = new THREE.Object3D(); RandomBlock.add(shape); blocks.push(RandomBlock); for (var i = 0; i < blocks.length; i++) { RandomBlock = blocks[i]; scene.add(RandomBlock); hit = false; } } function startSpawningEnemies() { repeater = setInterval(function() { spawnEnemy(); newBlock = false; }, 1000); } Basically it chooses a random object in the array 'shapes' and it adds the shape to the scene every second. But the problem is that when I have, for example a 'Leftblock' on screen and it randomly gets called again, Leftblock will get reset to the starting position, so basically I cant have 2 of the same type of block on screen at once. So I want want every block in the array to be an entirely new instance of a block, rather than the same. Here is a code pen so you can see what is happening My Codepen Thanks in advance Reply With Quote 01-31-2015, 12:06 PM #2 Lesshardtofind View Profile View Forum Posts Visit Homepage New Coder Join Date Sep 2013 Location Houston Posts 20 Thanks 0 Thanked 4 Times in 4 Posts Hey I apologize in advance this will probably be a long post, but to get to the root of your problem it takes a bit of explaining to show how I fixed it. If you don't want to read about all the changes and why I did them if you scroll to the bottom of this post the last code snippet is the new working code. Firstly I'd like to make a few comments. 1. Try to avoid using so many globals that is what is confusing the whole thing. 2. Even though JavaScript isn't a classical language. Using some OOP approaches can simplify your code quite a bit. Now to what your actual problem was. You only had one instance of meshes for each type of block/paddle or whatever you call it. Even though you created new 3d objects you still were just passing it the values of the current existing Meshes. In order to get around this I simplified your code a lot. I removed around 200 lines of code and created a few objects to make things easier. I don't know that I can explain every single thing I did, but creating objects is very useful for instance instead of making a ton of variables for each box you can make an Object called Box and then create a new instance of it. Since your Box also needs a mesh you can create that inside of the box as well. Code: function Box(w, h, d, q, m){ var CoreInfo = { width: w, height: h, depth: d, quality: q, material: m }; var Mesh = GetNewMesh(CoreInfo); this.setMeshY = function(y){ Mesh.position.y = y; } this.setMeshX = function(x){ Mesh.position.x = x; } this.getCoreInfo = function(key){ return CoreInfo[key]; } this.setCoreInfo = function(key, val){ CoreInfo[key] = val; } this.getAllInfo = function(){ return CoreInfo; } this.getMesh = function(){ return Mesh; } this.setShadows = function(r, c){ Mesh.receiveShadow = r; Mesh.castShadow = c; } } // you will notice that it calls this to get a MESH instead of using 5+ serperate calls you can now wrap it into a function that takes an assoc array. function GetNewMesh(info){ var Q = info["qaulity"]; return new THREE.Mesh( new THREE.BoxGeometry( info["width"], info["height"], info["depth"], Q, Q, Q), info["material"]); } With this object you can create new instances of boxes just by passing all the variables it needs and save it into a new object. example use: Code: var BlockMat = new THREE.MeshLambertMaterial({color: 0x3c00ff}); var Abox = new Box(10, 160, 10, 1, BlockMat); As you can see the Box requires 5 arguments to construct. They are width, height, depth, quality, and material; You will also notice there are functions inside of the Box to call functionality they are setMeshY(y): This sets the Y position of the mesh as the y value passed to it; setMeshX(x): This sets the X position of the mesh as the x value passed to it; getCoreInfo(key): This gets some CoreInfo based on a string or "key" that you pass it. EX use Box.getCoreInfo("width"); setCoreInfo(key, value): This sets some CoreInfo based on a string or "key" that you pass it. EX use Box.setCoreInfo("width", 100); getAllInfo(): Returns ALL CoreInfo in an assoc array that is accessed by a "key." EX use var AllInfo = Box.getAllInfo(); AllInfo["width"]; getMesh: Returns The mesh object setShadows: Allows you to set shadows by passing true or false for the receive and cast arguments. Now some of your enemy boxes needed two boxes so I further created a object called Double Box; These are very much the same as a box. Just all methods need to be passed an index as well. These are identical to your original objects as Paddle1 is now at index 0, and Paddle2 is at index1 for each respective object. With those objects created we can Delete a TON of your global variables and clean some stuff up. As a matter of fact the more I looked at it you didn't even NEED globals for your set enemy paddle types at all. I was able to wrap them all up into a function that will return an object like you wanted by being passed a string. Code: function GetBlock(type){ if(type == "m"){ var temp = new DoubleBox(10, 75, 10, 1, BlockMat, 10, 75, 10, 1, BlockMat); var obj = new THREE.Object3D(); obj.add(temp.getMesh(0)); obj.add(temp.getMesh(1)) temp.setMeshX(0, fieldWidth/2); temp.setMeshY(0, -60); temp.setMeshX(1, fieldWidth/2); temp.setMeshY(1, 60); return obj; } else if(type == "mr"){ var temp = new DoubleBox(10, 30, 10, 1,BlockMat, 10, 110, 10, 1,BlockMat); var obj = new THREE.Object3D(); obj.add(temp.getMesh(0)); obj.add(temp.getMesh(1)); temp.setMeshX(0, fieldWidth/2); temp.setMeshY(0, -80); temp.setMeshX(1, fieldWidth/2); temp.setMeshY(1, 40); return obj; } else if(type == "ml"){ var temp = new DoubleBox(10, 30, 10, 1, BlockMat, 10, 110, 10, 1, BlockMat); var obj = new THREE.Object3D(); obj.add(temp.getMesh(0)); obj.add(temp.getMesh(1)); temp.setMeshX(0, fieldWidth/2); temp.setMeshY(0, 80); temp.setMeshX(1, fieldWidth/2); temp.setMeshY(1, -40); return obj; } else if(type == "l"){ var temp = new Box(10, 160, 10, 1, BlockMat); var obj = new THREE.Object3D(); obj.add(temp.getMesh()); temp.setMeshX(fieldWidth/2); temp.setMeshY(20); return obj; } else if(type == "r"){ var temp = new Box(10, 160, 10, 1, BlockMat); var obj = new THREE.Object3D(); obj.add(temp.getMesh()); temp.setMeshX(fieldWidth/2); temp.setMeshY(-20); return obj; } } While this could be cleaned up and do some extra error checking it now does EXACTLY what you need it to. You can call this function and pass it a string for each type of block you want. It will return a NEW instance of that type of block without sharing meshes as you had previously programmed it to. now you can call this function in the spawn enemy function Code: function spawnEnemy() //total enemies starts at 0 and every-time you add to array { var shapes = ["l", "r", "mr", "ml", "m"]; // these are the strings that pass to the GetBlock(type) function as type var shape = shapes[Math.floor(Math.random() * shapes.length)]; blocks.push(new THREE.Object3D().add(GetBlock(shape))); // now you just pass the function to the THREE.Object3d().add() accepting shape as a parameter. for (var i = 0; i < blocks.length; i++) { RandomBlock = blocks[i]; scene.add(RandomBlock); hit = false; } } I know I made a lot of changes and there are still plenty more that could reduce your code even further, but when I finally got to a point where it was working the way you wanted to I figured I'd hand it back over to you. HERE is the final code that works if you want to copy paste it over to test it. Code: //scene object variables var renderer, scene, camera, pointLight, spotLight; var hit; var newBlock = false; //field variables var fieldWidth = 500, fieldHeight = 200; function GetNewMesh(info){ var Q = info["qaulity"]; return new THREE.Mesh( new THREE.BoxGeometry( info["width"], info["height"], info["depth"], Q, Q, Q), info["material"]); } function Box(w, h, d, q, m){ var CoreInfo = { width: w, height: h, depth: d, quality: q, material: m }; var Mesh = GetNewMesh(CoreInfo); this.setMeshY = function(y){ Mesh.position.y = y; } this.setMeshX = function(x){ Mesh.position.x = x; } this.getCoreInfo = function(key){ return CoreInfo[key]; } this.setCoreInfo = function(key, val){ CoreInfo[key] = val; } this.getAllInfo = function(){ return CoreInfo; } this.getMesh = function(){ return Mesh; } this.setShadows = function(r, c){ Mesh.receiveShadow = r; Mesh.castShadow = c; } } function DoubleBox(B1w, B1h, B1d, B1q, B1m, B2w, B2h, B2d, B2q, B2m) { var Boxes = []; Boxes[0] = new Box(B1w, B1h, B1d, B1q, B1m); Boxes[1] = new Box(B2w, B2h, B2d, B2q, B2m); this.setMeshY = function (index, y) { Boxes[index].setMeshY(y); } this.setMeshX = function (index, x) { Boxes[index].setMeshX(x); } this.getCoreInfo = function (index, key) { return Boxes[index].getCoreInfo(key); } this.setCoreInfo = function (index, key, val) { Boxes[index].setCoreInfo(key, val); } this.getAllInfo = function (index) { return Boxes[index].getAllInfo(); } this.getMesh = function (index) { return Boxes[index].getMesh(); } this.setShadows = function (index, r, c) { Boxes[index].setShadows(r, c); } } var BlockMat = new THREE.MeshLambertMaterial({color: 0x3c00ff}); var Player = new Box(10, 30, 10, 1, new THREE.MeshLambertMaterial({color: 0x4AA02C})); function GetBlock(type){ if(type == "m"){ var temp = new DoubleBox(10, 75, 10, 1, BlockMat, 10, 75, 10, 1, BlockMat); var obj = new THREE.Object3D(); obj.add(temp.getMesh(0)); obj.add(temp.getMesh(1)) temp.setMeshX(0, fieldWidth/2); temp.setMeshY(0, -60); temp.setMeshX(1, fieldWidth/2); temp.setMeshY(1, 60); return obj; } else if(type == "mr"){ var temp = new DoubleBox(10, 30, 10, 1,BlockMat, 10, 110, 10, 1,BlockMat); var obj = new THREE.Object3D(); obj.add(temp.getMesh(0)); obj.add(temp.getMesh(1)); temp.setMeshX(0, fieldWidth/2); temp.setMeshY(0, -80); temp.setMeshX(1, fieldWidth/2); temp.setMeshY(1, 40); return obj; } else if(type == "ml"){ var temp = new DoubleBox(10, 30, 10, 1, BlockMat, 10, 110, 10, 1, BlockMat); var obj = new THREE.Object3D(); obj.add(temp.getMesh(0)); obj.add(temp.getMesh(1)); temp.setMeshX(0, fieldWidth/2); temp.setMeshY(0, 80); temp.setMeshX(1, fieldWidth/2); temp.setMeshY(1, -40); return obj; } else if(type == "l"){ var temp = new Box(10, 160, 10, 1, BlockMat); var obj = new THREE.Object3D(); obj.add(temp.getMesh()); temp.setMeshX(fieldWidth/2); temp.setMeshY(20); return obj; } else if(type == "r"){ var temp = new Box(10, 160, 10, 1, BlockMat); var obj = new THREE.Object3D(); obj.add(temp.getMesh()); temp.setMeshX(fieldWidth/2); temp.setMeshY(-20); return obj; } } //ball variables var reftBlock, lightBlock, middleRightBlock, middleLeftBlock, middleBlock, RandomBlock; //game-related variables var score = 0; var repeater; var blocks = []; var collidableMeshList = []; function setup() { // update the board to reflect the max score for match win document.getElementById("winnerBoard").innerHTML = "Move in the gaps!"; // set up all the 3D objects in the scene createScene(); // and let's get cracking! draw(); } function createScene() { // set the scene size var WIDTH = 640, HEIGHT = 360; // set some camera attributes var VIEW_ANGLE = 50, ASPECT = WIDTH / HEIGHT, NEAR = 0.1, FAR = 10000; var c = document.getElementById("gameCanvas"); // create a WebGL renderer, camera // and a scene renderer = new THREE.WebGLRenderer({antialias:true}); renderer.setClearColorHex(0xffffff); camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR); scene = new THREE.Scene(); // add the camera to the scene scene.add(camera); // set a default position for the camera // not doing this somehow messes up shadow rendering //camera.position.z = 320; // start the renderer renderer.setSize(WIDTH, HEIGHT); // attach the render-supplied DOM element c.appendChild(renderer.domElement); // set up the playing surface plane var planeWidth = fieldWidth, planeHeight = fieldHeight, planeQuality = 10; // create the plane's material var planeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff }); // create the table's material var tableMaterial = new THREE.MeshLambertMaterial( { color: 0x3c00ff }); // create the ground's material var groundMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff }); // create the playing surface plane var plane = new THREE.Mesh( new THREE.PlaneGeometry( planeWidth * 1.25, // 95% of table width, since we want to show where the ball goes out-of-bounds planeHeight, planeQuality, planeQuality), planeMaterial); scene.add(plane); plane.receiveShadow = true; var table = new THREE.Mesh( new THREE.BoxGeometry( planeWidth * 1.15, // this creates the feel of a billiards table, with a lining planeHeight * 1.04, 100, // an arbitrary depth, the camera can't see much of it anyway planeQuality, planeQuality, 1), tableMaterial); table.position.z = -51; // we sink the table into the ground by 50 units. The extra 1 is so the plane can be seen scene.add(table); table.receiveShadow = true; scene.add(Player.getMesh()); startSpawningEnemies(); Player.setShadows(true, true) /*collidableMeshList.push(MiddleBlock.getMesh(0), MiddleBlock.getMesh(1), MiddleLeftBlock.getMesh(0), MiddleLeftBlock.getMesh(1), MiddleRightBlock.getMesh(0), MiddleRightBlock.getMesh(1), RightBlock.getMesh(), LeftBlock.getMesh());*/ // set paddles on each side of the table Player.setMeshX(-fieldWidth/2 + Player.getCoreInfo("width")); //collidableMeshList.push(RandomBlock); // finally we finish by adding a ground plane // to show off pretty shadows var ground = new THREE.Mesh( new THREE.BoxGeometry( 1000, 1000, 3, 1, 1, 1 ), groundMaterial); // set ground to arbitrary z position to best show off shadowing ground.position.z = -132; ground.receiveShadow = true; scene.add(ground); // // create a point light pointLight = new THREE.PointLight(0xffffff); // set its position pointLight.position.x = -1000; pointLight.position.y = 0; pointLight.position.z = 1000; pointLight.intensity = 2.9; pointLight.distance = 10000; // add to the scene scene.add(pointLight); // add a spot light // this is important for casting shadows spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(0, 0, 460); spotLight.intensity = 1.5; spotLight.castShadow = true; scene.add(spotLight); // MAGIC SHADOW CREATOR DELUXE EDITION with Lights PackTM DLC renderer.shadowMapEnabled = true; } function draw() { // draw THREE.JS scene renderer.render(scene, camera); // loop draw function call requestAnimationFrame(draw); cameraPhysics(); playerPaddleMovement(); enemyPaddleMovement(); collision(); //addScore(); } function addScore() { if (RandomBlock.position.x < Pad.getMesh().position.x*2 && newBlock == false) { console.log("pass"); newBlock = true; if (hit == false) { score++; } else { score-- } document.getElementById("scores").innerHTML = score; } } function enemyPaddleMovement() { if(score < 10) { for (var i = 0; i < blocks.length; i++) { blocks[i].position.x -= 3; } } if(score >= 10) { for (var i = 0; i < blocks.length; i++) { blocks[i].position.x -= 5; } } } function playerPaddleMovement() { if (Key.isDown(Key.D)) Player.setMeshY(80); else if (Key.isDown(Key.F)) Player.setMeshY(40); else if (Key.isDown(Key.H)) Player.setMeshY(0); else if (Key.isDown(Key.J)) Player.setMeshY(-40); else if (Key.isDown(Key.K)) Player.setMeshY(-80); } //Handles camera and lighting logic function cameraPhysics() { // move to behind the player's paddle camera.position.x = Player.getMesh().position.x - 100; camera.position.y += (Player.getMesh().position.y - camera.position.y) * 0.05; camera.position.z = Player.getMesh().position.z + 100 + 0.04 * (Player.getMesh().position.x); // rotate to face towards the opponent camera.rotation.y = -60 * Math.PI/180; camera.rotation.z = -90 * Math.PI/180; } //Handles paddle collision logic function collision() { var originPoint = Player.getMesh().position.clone(); for (var vertexIndex = 0; vertexIndex < Player.getMesh().geometry.vertices.length; vertexIndex++) { var ray = new THREE.Raycaster( originPoint, Player.getMesh().geometry.vertices[vertexIndex] ); var collisionResults = ray.intersectObjects( collidableMeshList ); if ( collisionResults.length > 0) { console.log("true"); hit = true; } } } function resetBall() { } //checks if either player or opponent has reached 7 points function matchScoreCheck() { } function spawnEnemy() //total enemies starts at 0 and every-time you add to array { var shapes = ["l", "r", "mr", "ml", "m"]; var shape = shapes[Math.floor(Math.random() * shapes.length)]; blocks.push(new THREE.Object3D().add(GetBlock(shape))); for (var i = 0; i < blocks.length; i++) { RandomBlock = blocks[i]; scene.add(RandomBlock); hit = false; } } function startSpawningEnemies() { repeater = setInterval(function() { spawnEnemy(); newBlock = false; }, 1000); //this calls spawnEnemy every spawnRate /////////spawn 'spawnAmount' enemies every 2 seconds } I also commented out your addScore() function because it references RandomBlock which is not defined in its scope and the error message was annoying for debugging. I also commented out the collision as you will need to think of a new method for doing that. Most likely just build a function that accepts an array and then just pass it your blocks array and let it loop through it. Overall cool game good luck to ya. Don't hesitate to reach out if you have any other questions. Reply With Quote Users who have thanked Lesshardtofind for this post: TeaAnyOne (01-31-2015) 01-31-2015, 02:31 PM #3 TeaAnyOne View Profile View Forum Posts New to the CF scene Join Date Jan 2015 Posts 4 Thanks 2 Thanked 0 Times in 0 Posts Wow! I didn't expect such a huge reply, it seems that my original code has changed a lot and I will have to give it a hard look through it to understand it. I will contact you if I have any questions, I have a lot of work ahead of me. Thanks a lot Reply With Quote 01-31-2015, 04:45 PM #4 TeaAnyOne View Profile View Forum Posts New to the CF scene Join Date Jan 2015 Posts 4 Thanks 2 Thanked 0 Times in 0 Posts I suppose I do have one more question. How do I get the position.x of the Randomblocks. I tried using a for loop like this: for (var i = 0; i < blocks.length; i++) { if (blocks[i].position.x === Player.getMesh().position.x*2 && newBlock === false) { console.log("pass"); newBlock = true; if (hit === false) { score++; } else { score--; } } document.getElementById("scores").innerHTML = score; } } it works but it seems kind of buggy as it stops counting to 10 when it changes speed. Is there another way to retrieve the position? Reply With Quote 01-31-2015, 07:43 PM #5 Lesshardtofind View Profile View Forum Posts Visit Homepage New Coder Join Date Sep 2013 Location Houston Posts 20 Thanks 0 Thanked 4 Times in 4 Posts That should work for getting the position since the Blocks are objects of type THREE.Object3d so any methods they have should work for you. You may be having problems because you never despawn enemies ultimately getting a huge number of 3d objects in your array blocks, or you may find your position requirement doesn't mathematically work with your speed up. Sometimes just using a few extra console.logs to track your numbers inside of functions that don't seem to be working can help you to get an idea of what values it is seeing for the numbers and when. It might make the problem super obvious. This more like shotgun debugging which is discouraged by many, but I found it to help a lot when I was first learning code. Ultimately you want to understand your logic in each function and how it can fail when you program it, and then use error checking to make sure no parameters get outside of your allowed variance. Reply With Quote Users who have thanked Lesshardtofind for this post: TeaAnyOne (01-31-2015) 01-31-2015, 08:27 PM #6 TeaAnyOne View Profile View Forum Posts New to the CF scene Join Date Jan 2015 Posts 4 Thanks 2 Thanked 0 Times in 0 Posts OK ill see if I can get it working. Thanks for all your help! It helped me a lot. Reply With Quote 01-31-2015, 08:31 PM #7 Old Pedant View Profile View Forum Posts Supreme Master coder! Join Date Feb 2009 Posts 28,310 Thanks 82 Thanked 4,754 Times in 4,716 Posts Originally Posted by Lesshardtofind Ultimately you want to understand your logic in each function and how it can fail when you program it, and then use error checking to make sure no parameters get outside of your allowed variance. Very well said! I have a problem. I have created a rotating picture array. The problem I am having is when I view the web page only the right side of my array rotates through the pictures. I have tried several ways to fix this, but have ran out of ideas. Code: <script type="text/javascript"> <!--Hide from old browsers var rotatePicsLeft= Array("candle1.jpg","candle2.jpg","candle3.jpg","candle4.jpg","candle5.jpg","candle6.jpg") var rotatorCntr=5 function RotateIt() { rotatorCntr+=1 if (rotatorCntr==6) rotatorCntr=0 document.picture1.src = rotatePicsLeft[rotatorCntr] setTimeout("RotateIt()",2000) } var rotatePicsRight=new Array("flowers1.jpg","flowers2.jpg","flowers3.jpg","flowers4.jpg","flowers5.jpg","flowers6.jpg","flowers7.jpg","flowers8.jpg") var rotatorCntr=7 function RotateIt() { rotatorCntr+=1 if (rotatorCntr==8) rotatorCntr=0 document.picture2.src = rotatePicsRight[rotatorCntr] setTimeout("RotateIt()",2000) } //--> </script> Any ideas would be greatly appreciated. Thanks Hi, I am stumped. I have been trying unsuccesfully for three days to figure something out, and it has brought me here. I am a noob javascripter, so please bear with me. I have created a page with an input button that refers to a function: Code: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="generator" content="CoffeeCup HTML Editor (www.coffeecup.com)"> <meta name="created" content="Thu, 26 May 2011 03:39:57 GMT"> <meta name="description" content=""> <meta name="keywords" content=""> <title>Meltmedia Web Intern Test</title> <style type="text/css"> <!-- body { color:#000000; background-color:#FFFFFF; } a { color:#0000FF; } a:visited { color:#800080; } a:hover { color:#008000; } a:active { color:#FF0000; } --> </style> <!--[if IE]> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <LINK REL=StyleSheet HREF="what.css" TYPE="text/css" MEDIA=screen> <script type="text/javascript"> //function ChangeBackground() <!--{ // document.getElementById("column2").style.backgroundColor="#ffbdaa"; // document.getElementById("row1").style.backgroundColor="#ffbdaa"; // document.getElementById("row3").style.backgroundColor="#ffbdaa"; // document.getElementById("row4").style.backgroundColor="#ffbdaa"; // document.getElementById("mainbody").style.backgroundColor="#f7d7cd"; // } --> function ChangeBackground() { var colors = document.getElementsByClassName("changeme"); //alert(colors.length); for (var i = 0; i < colors.length; i++) { if (colors[i].className="changeme") { colors[i].style.backgroundColor="ffbdaa"; } } } //if (document.getElementsByClassName('changeme')[5].style.backgroundColor="#e8e8e00") { // document.getElementsByClassName('changeme')[5].style.backgroundColor="#ffbdaa"; // } //div1 original color is #e8e8e8 //div2 original color is #e2ebe4 //tablerows original color is #ccddd0 </script> </head> <body> <div id="mainbody" class="changeme"> <img id="header" src="osx_header.jpg"> <div id="inset"> <div id="column1" class="column1"> <p class="text0">Lorem Ipsum Dolor Sit Amet</p> <p class="text1">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sed est et mi varius euismod sed nec neque. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas ultricies pulvinar lacinia. <a href="http://www.google.com/" rel="nofollow" target="_blank" style="color:blue">This is a link.</a> </p> <p class="text1" style="font-size:16px;">Lorem Ipsum Dolor Sit Amet</p> <p class="text1">Sed a felis et eros gravida dignissim. Quisque lobortis magna non purus vulputate pellentesque. Mauris sit amet felis felis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam molestie lacinia arcu vitae pretium.<sup>2.3</sup> </p> <div id="unordered_list"> <ul id="blue_bullets"> <li>Vestibulum ante erat, laoreet quis pellentesque quis, tincidunt fermentum turpis. <li>Maecenas in mollis massa. <ul> <li>Ut tempus tincidunt molestie. Phasellus eget nulla id erat scelerisque porttitor vel pharetra nibh. <li>Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </ul> <li>Aenean ligula massa, tempor sed pulvinar sit amet, imperdiet a nisi. </ul> </div><!--end of ordered list--> <div id="button"> <!-- <img src="btn-click-here.gif"> --> <input type="button" onClick="ChangeBackground()" value=" "> </div><!--end of button--> <table id="table1"> <tr id="firstrow"> <th id="row1" class="changeme"></th> <th id="row2" class="changeme"><strong>header1</strong></th> <th id="row3" class="changeme"><strong>header2</strong></th> <th id="row4" class="changeme"><strong>header3</strong></th> </tr> <tr> <td>one</td> <td>1234</td> <td>bears</td> <td>abcd</td> </tr> <tr> <td>two</td> <td>5678</td> <td>beets</td> <td>efgh</td> </tr> <tr> <td>three</td> <td>9101</td> <td>battlestar</td> <td>ijkl</td> </tr> <tr> <td>four</td> <td>1121</td> <td>galactica</td> <td>mnop</td> </tr> </table> <!--end of table--> <ol class="ordered"> <li>Integer molestie sodales risus eu commodo. <i>Duis eget est dapibus neque congue</i> accumsan id eu nibh. </li> <li>Proin malesuada hendrerit lobortis. Integer et erat leo. Praesent nec justo nulla. <i>Sed in dolor id neque faucibus consequat.</i> </li> <li>Vestibulum sit amet justo id <strong>risus tempus ornare.</strong> Etiam faucibus urna volutpat lorem dictum imperdiet. </li> </ol> </div> <!--end of column1--> <div id="column2" class="changeme"> <p class="text00"><strong>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</strong></p> <p class="text2">Aenean sed est et mi varius euismod sed nec neque. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas ultricies pulvinar lacinia. Sed a felis et eros gravida dignissim. Quisque lobortis magna non purus vulputate pellentesque.</p> <p class="text2">Mauris sit amet felis felis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam molestie lacinia arcu vitae pretium. Vestibulum ante erat, laoreet quis pellentesque quis, tincidunt fermentum turpis. Maecenas in mollis massa. Ut tempus tincidunt molestie.</p> <p class="text2">Phasellus eget nulla id erat scelerisque porttitor vel pharetra nibh. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean ligula massa, tempor sed pulvinar sit amet, imperdiet a nisi. Nulla ullamcorper posuere dolor, ac rutrum velit sollicitudin ac. Ut felis leo, ultricies a bibendum ac, luctus semper massa.</p> </div> <!--end of column2--> </div> <!--end of inset--> </div> </body> </html> i would like to change certain style elements of the array each time the button is clicked. I have 5 color sets i would like use for the page, so i would like the button to trigger the color change in a loop, ie when the last color group is reached, the next click returns to the original color set and it continues again. This is a demo page, not for actually publication. I am trying to teach myself javascript and this is an idea that came to me. The things i want to change are the background color of two div's and the top row of a table. My style sheet is seperate, and I will also do the same for the javascript once I can get it to work properly. Thank you in advance for any help. Hi all, I create textboxes dynamically by the following code function addElement() { var contentID = document.getElementById('content'); var newTBDiv = document.createElement('div'); newTBDiv.setAttribute('id','strText'+intTextBox); divname='strText'+intTextBox; newTBDiv.innerHTML = "Text "+intTextBox+": <input type='text' id='divid' +intTextBox name='txtbx[]'/>"; intTextBox = intTextBox + 1; contentID.appendChild(newTBDiv); } It works fine,but i want to get the values and validate it so i use the following code.. var idval=new Array(); for(var i=0;i<intTextBox;i++) { idval[i]=document.getElementById('divid').value; alert(idval[i]); } but it didn`t work out,Any suggestions really helpful. Thankyou. |