Web Analytics Made Easy -
StatCounter What's better to use? innerHTML or appendChild - CodingForum

Announcement

Collapse
No announcement yet.

What's better to use? innerHTML or appendChild

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • What's better to use? innerHTML or appendChild

    I'm making a tool to get all the colors onmouseover via an image map. I'm making the script draw a block for every color on a canvas which I'll save after it's rendered and use for an image map.

    first I make the huge array with the colors. Im going to make it work on the canvas without an image map too, but for non canvas browsers I'll use the image and the image map. the image map HTML is 4096 lines. YIKES!!!

    I have it working using innerHTML to feed div with the correct info to make the image map at the same time each block is drawn. Simple actually, but 5K lines of HTML is just ridiculous.

    I think the problem is I have to use
    Code:
    readout.innerHTML+="..."
    because
    Code:
    readout.innerHTML="..."
    only draws the last thing you give it. But as it is, it's just too much HTML to rewrite each iteration. the page begins by slapping the html at light speed, but slows to a crawl after only a few hundred lines. and I've not seen it reach script's end.


    Should I use appendChild? create textNode?

    What the best idea? What would you do?
    I think maybe i should just create elements and style them instead? But then it wouldn't be an image map, now would it? heheh

  • #2
    Here's a dumbass idea: Forget the image map.

    Instead, just find the x,y location where the mouse was clicked and *calculate* what color is there. (I assume you can do that if you can calculate what color goes with what value in the map.)

    Should be much more efficient.
    Be yourself. No one else is as qualified.

    Comment


    • #3
      And, if on some other project, you really do need to insert a ton of HTML into a page...
      Code:
      while(youFeelLikeIt){
        // do stuff that produces HTML
        arrayOfStrings.push(anotherStringOfHTML);
      }
      element.innerHTML=arrayOfStrings.join("");
      Saves the overhead of repeated string-concatenation, and the new HTML is parsed only once.

      Comment


      • #4
        Cute trick! I like it!
        Be yourself. No one else is as qualified.

        Comment


        • #5
          Originally posted by Old Pedant View Post
          Here's a dumbass idea: Forget the image map.

          Instead, just find the x,y location where the mouse was clicked and *calculate* what color is there. (I assume you can do that if you can calculate what color goes with what value in the map.)

          Should be much more efficient.
          I know, that's next ! LOL but I'm also trying to learn how to build data efficiently.
          Plus it works awesome. Here's a link.
          http://h1.ripway.com/stirfry/javascr...lorpicker.html

          this is the end product.

          here's the builder script. How would I integrate the join()?
          I'm cluless.
          Code:
          <html>
            <head>
          <style type="text/css">
                body { margin: 20px; font-family: arial,verdana,helvetica; background: #fff;}
                 canvas { background-color:black;border: 0px solid #000; }
                 </style>
          <script type="text/javascript" src="excanvas.js"></script>
          </head>
          <body onload="drawshape()">
          <script type="text/javascript">
          var indexnum=0;
          var indexnumBuildMap=0;
          var colors=new Array()
          var colornums=new Array();
          function drawshape(){
           var readout=document.getElementById("readout");
          for (Cnums=0;Cnums<10;Cnums++){colornums[Cnums]=''+Cnums+''+Cnums+''}
          colornums[10]='AA';
          colornums[11]='BB';
          colornums[12]='CC';
          colornums[13]='DD';
          colornums[14]='EE';
          colornums[15]='FF';
          
          for(c=0;c<16;c++){
          		for (a=0;a<16;a++){
          				for(b=0;b<16;b++){
          
          		colors[indexnum]='#'+colornums[a]+''+colornums[15-c]+''+colornums[b]+'';
          indexnum++;
          }	}	}/*end loop*/
          
          }
           /*YIKES!!! don't even attempt to draw all the HTML at once. SET count to some multiple of 256. i would suggest creating blocks of half or quarter the entire list of 4096 areas*/
          var count=0;
          setTimeout("draw()",1000)
          
          
           var addToY=0;
          var addX=0;
          var mapindex=0;
          
          function draw(){
          	/*boolean...controls html build seperately*/
          if (count==1){
          var readout=document.getElementById('readout');
          }
          	/*boolean controls...canvas build seperately*/
          if (count==0){
          canvas=document.getElementById('canvas');
           ctx= canvas.getContext('2d');
          }
          
          /*sets size of Y shift by index num every 256. when index num/256 ==0   y+=1  ...x becomes 0 every 256*/
          if (mapindex>0&&mapindex%256==0) {addToY+=1;addX%=256;}
          
          /*boolean...controls  canvas build seperately*/
          if (count==0){
          ctx.fillStyle=colors[mapindex];
          ctx.fillRect(addX*3,(addToY*3),3,3);
          }
          
          /*boolean...controls html build seperately*/
          if (count==1){
          readout.innerHTML+="&lt;area shape=";
          readout.innerHTML+="\"";
          readout.innerHTML+="rect";
          readout.innerHTML+="\""; 
          readout.innerHTML+="coords=";
          readout.innerHTML+="\"";
          readout.innerHTML+=addX*3;
          readout.innerHTML+=",";
          readout.innerHTML+=addToY*3;
          readout.innerHTML+=",";
          readout.innerHTML+=addX*3+3;
          readout.innerHTML+=",";
          readout.innerHTML+=addToY*3+3
          readout.innerHTML+="\"";
          readout.innerHTML+="    href=";
          readout.innerHTML+="\"";
          readout.innerHTML+="javascript:showColor('";
          readout.innerHTML+=colors[mapindex];
          readout.innerHTML+="')";
          readout.innerHTML+="\"";
          readout.innerHTML+="onmouseover=";
          readout.innerHTML+="\"";
          readout.innerHTML+="update('"
          readout.innerHTML+=colors[mapindex];
          readout.innerHTML+="')"
          readout.innerHTML+="\"";
          readout.innerHTML+="><br>";
          }
          mapindex++;
          addX++;
          if (mapindex<4096){setTimeout("draw()",2)}
          if (mapindex==4096&&count==0){count++;mapindex=0;addX=0;addToY=0;setTimeout("draw()",15)}
          if (mapindex==4096&&count==1){setTimeout("end()",15)}
          }
          function end(){readout.innerHTML+="End";}
          </script>
          <canvas id="canvas" width="769" height="49" ></canvas>
          <div id="readout" style="position:absolute;top:500px;width:100%;"></div>
          </body>
          </html>
          I tried to make it one line of code but it wouldn't work no matter what I tried

          Comment


          • #6
            What I think will be best is to create elements with the names based on the mouse events the mouse coordinates and then use the counting system with the color id for for multiple categories like borders,fonts ...blah blah

            Comment


            • #7
              OUCH! No WONDER you have problems!!!

              The WORST thing you can do is the way you are building the HTML! You aren't even giving it valid HTML after each append!

              *AT A MINIMUM* you should ZAP this code:
              Code:
              /*boolean...controls html build seperately*/
              if (count==1){
              readout.innerHTML+="&lt;area shape=";
              readout.innerHTML+="\"";
              readout.innerHTML+="rect";
              readout.innerHTML+="\""; 
              readout.innerHTML+="coords=";
              readout.innerHTML+="\"";
              readout.innerHTML+=addX*3;
              readout.innerHTML+=",";
              readout.innerHTML+=addToY*3;
              readout.innerHTML+=",";
              readout.innerHTML+=addX*3+3;
              readout.innerHTML+=",";
              readout.innerHTML+=addToY*3+3
              readout.innerHTML+="\"";
              readout.innerHTML+="    href=";
              readout.innerHTML+="\"";
              readout.innerHTML+="javascript:showColor('";
              readout.innerHTML+=colors[mapindex];
              readout.innerHTML+="')";
              readout.innerHTML+="\"";
              readout.innerHTML+="onmouseover=";
              readout.innerHTML+="\"";
              readout.innerHTML+="update('"
              readout.innerHTML+=colors[mapindex];
              readout.innerHTML+="')"
              readout.innerHTML+="\"";
              readout.innerHTML+="><br>";
              }
              For this:
              Code:
              /*boolean...controls html build seperately*/
              if (count==1)
              {
                  var h = "&lt;area shape=\"rect\" coords=\"" 
                  h +=addX*3;
                  h +=",";
                  h +=addToY*3;
                  h +=",";
                  h +=addX*3+3;
                  h +=",";
                  h +=addToY*3+3
                  h +="\"";
                  h +="    href=\"javascript:showColor('" +colors[mapindex] + "')\"";
                  h +="onmouseover=\"update('" + colors[mapindex] + "')\"><br>";
                  readout.innerHTML += h;
              }
              So that you are only appending once per item.

              But what Shannon was talking about would be this:
              Code:
              ...
              var allAreas = new Array(); // put this outside any loops, at start of code
              
              if (count==1)
              {
                  var h = "&lt;area shape=\"rect\" coords=\"" 
                  h +=addX*3;
                  h +=",";
                  h +=addToY*3;
                  h +=",";
                  h +=addX*3+3;
                  h +=",";
                  h +=addToY*3+3
                  h +="\"";
                  h +="    href=\"javascript:showColor('" +colors[mapindex] + "')\"";
                  h +="onmouseover=\"update('" + colors[mapindex] + "')\"><br>";
                  allAreas.push( h );
              }
              And then, after you have collected *ALL* of those areas in the array:

              Code:
                  readout.innerHTML += allAreas.join( );
              Be yourself. No one else is as qualified.

              Comment


              • #8
                you guys are so awesome! Thanks. I knew i was trying to chip rocks with banana peels.
                heheh this is funny. I'm pretty embarrassed, but that's what this forum is for to me, a place to learn from mistakes.



                just tested it. it took less than a minute and I didn't change the timeouts from 15ms. Thanks again!
                Last edited by TinyScript; Apr 14, 2009, 08:14 PM. Reason: tested

                Comment


                • #9
                  how could I get that HTML to become code for the page? I can use toDataURL() to pass the canvas to the image map and then move the canvas off the screen that solves the browser with no canvas problem. Can I put the html in a div that's sized to zero?
                  Last edited by TinyScript; Apr 14, 2009, 08:23 PM.

                  Comment


                  • #10
                    Ummm...I don't think that <area>'s actually use any space on the screen, in any case.

                    They are really just hidden controls, already. So why do you need to move the canvas off the screen???

                    You know, you *could* do this same code in, say, PHP. And then just do a VIEW-->>SOURCE to get the HTML. And then dump the PHP and just include the HTML as a file right in the page.

                    Why generate this each time???

                    Alternatively, after you generate this, you could just do
                    Code:
                    document.write(allAreas.join().replace("<","&lt;").replace(">","&gt;") );
                    And then just copy/paste from the browser screen into notepad and then just use that as static HTML.

                    Ummm...I always forget that replace takes a regexp. So:
                    Code:
                    document.write(allAreas.join().replace( /\</g,"&lt;").replace(/\>/g,"&gt;") );
                    Be yourself. No one else is as qualified.

                    Comment


                    • #11
                      Originally posted by Old Pedant View Post
                      Ummm...I don't think that <area>'s actually use any space on the screen, in any case.

                      They are really just hidden controls, already. So why do you need to move the canvas off the screen???

                      You know, you *could* do this same code in, say, PHP. And then just do a VIEW-->>SOURCE to get the HTML. And then dump the PHP and just include the HTML as a file right in the page.

                      Why generate this each time???

                      Alternatively, after you generate this, you could just do
                      Code:
                      document.write(allAreas.join().replace("<","&lt;").replace(">","&gt;") );
                      And then just copy/paste from the browser screen into notepad and then just use that as static HTML.

                      Ummm...I always forget that replace takes a regexp. So:
                      Code:
                      document.write(allAreas.join().replace( /\</g,"&lt;").replace(/\>/g,"&gt;") );
                      I want to have the pre-made page for javascript disabled browsers and have the image used for that on the page already if the user is not using javascript. But if they are, the image will be created in front of them and then I'll move the canvas when it's done, since I'm not sure you can use the same image map function on the canvas without making another function, I'm going to give the move the canvas off the screen and then I can add animations to the canvas that will show up when I send the data to the color pic later on with todataURL. So I would like to build the html rather than send 500K of html

                      Comment


                      • #12
                        But if this thing takes a minute to create, how many people are going to sit around that long???

                        And I *HOPE* you are wrong about not being able to use the same <area>s for more than one image, else it will take a truly monstrously long time!

                        I *REALLY* think it's time to abandon a map that is this big and go for the clicked-on spot, instead. On top of that, you'll be able to use the same function on multiple maps, by just adjusting for where the top-left corner of the individual map is located.

                        You could probably have that up and working in less time than it will take to finish this messy thing.

                        As for people with JS disabled: Okay, easy answer on that one.

                        If you use <input type="image">, then when the user clicks on the image the page is submitted back to the server *WITH THE x/y location of the clicked on spot!*

                        That is, if you have
                        <input type=image name=colors1>
                        then the server will receive (in query string or in post, as appropriate) values for
                        colors1.x
                        and
                        colors1.y
                        And they *ARE* relative to the top/left of the image!
                        Be yourself. No one else is as qualified.

                        Comment


                        • #13
                          Originally posted by Old Pedant View Post
                          But if this thing takes a minute to create, how many people are going to sit around that long???

                          And I *HOPE* you are wrong about not being able to use the same <area>s for more than one image, else it will take a truly monstrously long time!

                          I *REALLY* think it's time to abandon a map that is this big and go for the clicked-on spot, instead. On top of that, you'll be able to use the same function on multiple maps, by just adjusting for where the top-left corner of the individual map is located.

                          You could probably have that up and working in less time than it will take to finish this messy thing.

                          As for people with JS disabled: Okay, easy answer on that one.

                          If you use <input type="image">, then when the user clicks on the image the page is submitted back to the server *WITH THE x/y location of the clicked on spot!*

                          That is, if you have
                          <input type=image name=colors1>
                          then the server will receive (in query string or in post, as appropriate) values for
                          colors1.x
                          and
                          colors1.y
                          And they *ARE* relative to the top/left of the image!
                          I don't know how to do that yet. I'm still trying to figure out how to use php scripts. I can't get any help because my questions are too general or appear stupid.

                          Comment


                          • #14
                            the canvas renders in 2 seconds, and the html renders in about 10 seconds, but it's not hidden. What am I doing wrong?


                            Code:
                            <html>
                              <head>
                            <style type="text/css">
                                  body { margin: 20px; font-family: arial,verdana,helvetica; background: #fff;}
                                   canvas { background-color:black;border: 0px solid #000; }
                                   </style>
                            <script type="text/javascript" src="excanvas.js"></script>
                            </head>
                            
                              <body onload="drawshape()">
                            <script type="text/javascript">
                            var allAreas = new Array(); // put this outside any loops, at start of code
                            
                            var indexnum=0;
                            var indexnumBuildMap=0;
                            var colors=new Array()
                            var colornums=new Array();
                            
                            function drawshape(){
                             var readout=document.getElementById("readout");
                            for (Cnums=0;Cnums<10;Cnums++){colornums[Cnums]=''+Cnums+''+Cnums+''}
                            colornums[10]='AA';
                            colornums[11]='BB';
                            colornums[12]='CC';
                            colornums[13]='DD';
                            colornums[14]='EE';
                            colornums[15]='FF';
                            
                            
                             
                            for(c=0;c<16;c++){
                            		for (a=0;a<16;a++){
                            				for(b=0;b<16;b++){
                            
                            		colors[indexnum]='#'+colornums[a]+''+colornums[15-c]+''+colornums[b]+'';
                            indexnum++;
                            }	}	}/*end loop*/
                            setTimeout("draw()",1000)
                            }
                             //readout.innerHTML+='hello<br>';
                            
                            
                            
                            var readout=document.getElementById("readout");
                            
                            function draw(){
                            //alert(indexnum);
                            canvas=document.getElementById('canvas');
                             ctx= canvas.getContext('2d');
                            var readout=document.getElementById('readout');
                             var addToY=0;
                            var addX=0;
                            for(indexColors=0;indexColors<indexnum;indexColors++){
                            var index=indexColors;
                            if (index>0&&index%256==0) {addToY+=1;addX%=256;}
                            ctx.fillStyle=colors[indexColors];
                            ctx.fillRect(addX*3,(addToY*3),3,3);
                            
                            
                            
                                var h = "&lt;area shape=\"rect\" coords=\"" 
                                h +=addX*3;
                                h +=",";
                                h +=addToY*3;
                                h +=",";
                                h +=addX*3+3;
                                h +=",";
                                h +=addToY*3+3
                                h +="\"";
                                h +="    href=\"javascript:showColor('" +colors[indexColors] + "')\"";
                                h +="onmouseover=\"update('" + colors[indexColors] + "')\"><br>";
                                allAreas.push( h );
                            addX++;
                            }
                            
                            
                            if (indexColors==4096){document.write(allAreas.join().replace( /\</g,"&lt;").replace(/\>/g,"&gt;") );addX=0;addToy=0;
                            
                            
                            for(index=0;index<indexColors;index++){
                            
                            if (index>0&&index%256==0) {addToY+=1;addX%=256;}
                            ctx.fillStyle=colors[index];
                            ctx.fillRect(addX*3,(addToY*3),3,3);
                            addX++;
                            }
                            }
                            }
                            
                            
                            
                            //alert(colors[4095])/*final possibility*/
                            </script>
                            
                              <canvas id="canvas" width="769" height="49" ></canvas>
                            
                                <div id="readout" style="position:absolute;top:500px;width:100%;height:200px"></div>
                            
                               
                                 
                                 
                              </body>
                            
                            </html>

                            Comment


                            • #15
                              Two things:

                              (1) You are doing
                              var h = "&lt;area shape=\"rect\" coords=\""

                              So of course you are *NOT* generating HTML, at all. HTML needs *REAL* < and > tag marks. So:
                              var h = "<area shape=\"rect\" coords=\""

                              (2) That code I suggested was JUST FOR DEBUGGING!
                              document.write(allAreas.join().replace( /\</g,"&lt;").replace(/\>/g,"&gt;")

                              When you use the replace like that, indeed *AGAIN* you are ensuring that you are *NOT* producing HTML! You are making sure that the < and > tag delimiters DO NOT appear.

                              Also, you need to use join("") or JS puts commas into the joined string. So:
                              document.write(allAreas.join(""))

                              But I am still not SURE that is right.
                              Be yourself. No one else is as qualified.

                              Comment

                              Working...
                              X