Nick Audenaerde
Nick Audenaerde

Reputation: 1025

How to use the same JS for same HTML multiple times

I used this from another stackoverflow question: http://jsfiddle.net/Aapn8/3410/ to create circle progress bars.

Except when I'm trying to create more then 1, nothing happens how can you clean fix this without copying the JavaScript and change just 1 var.

This is my code:

.circleWrapper {
  width: 250px;
  float: left;
}
.circleText {} .circleTextSmall {} #graph div {
  position: relative;
  margin: 80px;
  width: 220px;
  height: 220px;
}
#graph canvas {
  display: block;
  top: 0;
  left: 0;
}
#graph span {
  color: #555;
  display: block;
  line-height: 220px;
  text-align: center;
  width: 220px;
  font-family: sans-serif;
  font-size: 40px;
  font-weight: 100;
  margin-left: 5px;
}
#graph input {
  width: 200px;
}
<div class="circleWrapper">
  <div class="chart" id="graph" data-percent="50"></div>
  <div class="circleText">HTML/CSS</div>
  <div class="circleTextSmall">Small text</div>
</div>

<div class="circleWrapper">
  <div class="chart" id="graph" data-percent="45"></div>
  <div class="circleText">PHP</div>
  <div class="circleTextSmall">Small text</div>
</div>

Upvotes: 2

Views: 2076

Answers (4)

yarwest
yarwest

Reputation: 990

You have used the graph ID twice. You can only use an ID once per document.

The id attribute specifies a unique id for an HTML element (the value must be unique within the HTML document).

More information on this can be found here.

Change the ID to something else and change the JS to interact with both elements.

This can for example be done with getElementsByClassName(). This function returns an array of elements instead of a single element.

I think it is best if you wrap all your functionality in a function with the following signature:

function startGraph(el) {
    ...
}

and then call the function from this for-loop:

var elements = document.getElementsByClassName("chart");
var i;
for (i = 0; i < x.length; i++) {
    startGraph(elements[i]);
}

More information on that can be found here.

Upvotes: 2

vishal patel
vishal patel

Reputation: 832

var els = document.getElementsByClassName("chart");
for(var i=0; i < els.length; i++){

    var el = els[i];

    var options = {
        percent:  el.getAttribute('data-percent') || 25,
        size: el.getAttribute('data-size') || 220,
        lineWidth: el.getAttribute('data-line') || 15,
        rotate: el.getAttribute('data-rotate') || 0
    }

    var canvas = document.createElement('canvas');
    var span = document.createElement('span');
    span.textContent = options.percent + '%';
    
    if (typeof(G_vmlCanvasManager) !== 'undefined') {
        G_vmlCanvasManager.initElement(canvas);
    }

    var ctx = canvas.getContext('2d');
    canvas.width = canvas.height = options.size;

    el.appendChild(span);
    el.appendChild(canvas);

    ctx.translate(options.size / 2, options.size / 2); // change center
    ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg

    //imd = ctx.getImageData(0, 0, 240, 240);
    var radius = (options.size - options.lineWidth) / 2;

    var drawCircle = function(color, lineWidth, percent) {
		percent = Math.min(Math.max(0, percent || 1), 1);
		ctx.beginPath();
		ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
		ctx.strokeStyle = color;
        ctx.lineCap = 'round'; // butt, round or square
		ctx.lineWidth = lineWidth
		ctx.stroke();
     };

    drawCircle('#efefef', options.lineWidth, 100 / 100);
    drawCircle('#555555', options.lineWidth, options.percent / 100);
}
div {
    position:relative;
    margin:80px;
    width:220px; height:220px;
}
canvas {
    display: block;
    position:absolute;
    top:0;
    left:0;
}
span {
    color:#555;
    display:block;
    line-height:220px;
    text-align:center;
    width:220px;
    font-family:sans-serif;
    font-size:40px;
    font-weight:100;
    margin-left:5px;
}

input {
    width: 200px;
}

span {
  
}
<div class="chart"  data-percent="88"></div>
<div class="chart"  data-percent="78"></div>

Upvotes: 3

Luke Briggs
Luke Briggs

Reputation: 3789

Use functions

Put your code inside a function which accepts some way of identifying a particular element, then call that function multiple times. Here's a fork of that fiddle as a working example:

function startGraph(el) { // turn it into a function which accepts an element
  
  // (Nothing else has changed)
  var options = {
      percent:  el.getAttribute('data-percent') || 25,
      size: el.getAttribute('data-size') || 220,
      lineWidth: el.getAttribute('data-line') || 15,
      rotate: el.getAttribute('data-rotate') || 0
  }

  var canvas = document.createElement('canvas');
  var span = document.createElement('span');
  span.textContent = options.percent + '%';

  if (typeof(G_vmlCanvasManager) !== 'undefined') {
      G_vmlCanvasManager.initElement(canvas);
  }

  var ctx = canvas.getContext('2d');
  canvas.width = canvas.height = options.size;

  el.appendChild(span);
  el.appendChild(canvas);

  ctx.translate(options.size / 2, options.size / 2); // change center
  ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg

  //imd = ctx.getImageData(0, 0, 240, 240);
  var radius = (options.size - options.lineWidth) / 2;

  var drawCircle = function(color, lineWidth, percent) {
      percent = Math.min(Math.max(0, percent || 1), 1);
      ctx.beginPath();
      ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
      ctx.strokeStyle = color;
          ctx.lineCap = 'round'; // butt, round or square
      ctx.lineWidth = lineWidth
      ctx.stroke();
  };

  drawCircle('#efefef', options.lineWidth, 100 / 100);
  drawCircle('#555555', options.lineWidth, options.percent / 100);
}

Assuming each element has class="chart" then you can get all the elements and call the function with each one:

// Get all charts:
var myCharts=document.getElementsByClassName("chart");

// For each one..
for (var i in myCharts) {
   // Start it:
   startGraph(myCharts[i]);
}

Upvotes: 3

All you need to do is to define unique ids in your HTML, and define an array of all your graph elements and loop through the logic, see this as an example:

var elements = [{
  'id': 'graph1'
}, {
  'id': 'graph2'
}];

for (var i = 0; i < elements.length; i++) {
  var el = document.getElementById(elements[i]['id']);
  var options = {
    percent: el.getAttribute('data-percent') || 25,
    size: el.getAttribute('data-size') || 220,
    lineWidth: el.getAttribute('data-line') || 15,
    rotate: el.getAttribute('data-rotate') || 0
  }

  var canvas = document.createElement('canvas');
  var span = document.createElement('span');
  span.textContent = options.percent + '%';

  if (typeof(G_vmlCanvasManager) !== 'undefined') {
    G_vmlCanvasManager.initElement(canvas);
  }

  var ctx = canvas.getContext('2d');
  canvas.width = canvas.height = options.size;

  el.appendChild(span);
  el.appendChild(canvas);

  ctx.translate(options.size / 2, options.size / 2); // change center
  ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg

  //imd = ctx.getImageData(0, 0, 240, 240);
  var radius = (options.size - options.lineWidth) / 2;

  var drawCircle = function(color, lineWidth, percent) {
    percent = Math.min(Math.max(0, percent || 1), 1);
    ctx.beginPath();
    ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
    ctx.strokeStyle = color;
    ctx.lineCap = 'round'; // butt, round or square
    ctx.lineWidth = lineWidth
    ctx.stroke();
  };

  drawCircle('#efefef', options.lineWidth, 100 / 100);
  drawCircle('#555555', options.lineWidth, options.percent / 100);

}
div {
  position: relative;
  margin: 80px;
  width: 220px;
  height: 220px;
}
canvas {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
}
span {
  color: #555;
  display: block;
  line-height: 220px;
  text-align: center;
  width: 220px;
  font-family: sans-serif;
  font-size: 40px;
  font-weight: 100;
  margin-left: 5px;
}
input {
  width: 200px;
}
span {}
<div class="chart" id="graph1" data-percent="88"></div>
<div class="chart" id="graph2" data-percent="25"></div>

Upvotes: 1

Related Questions